<text><span class="style3">n introduction to programming using an object-oriented extension to the C language, Symantec Corporation's Think C 5.0 for Macintosh computers. Also suitable as an introduction to the C++ language. No C programming experience is assumed.
</span><span class="style21">
</span><span class="style3">Includes sample code for graphics and for studying application frameworks.
Price: $20. Ralph Gonzalez, PO Box 54, Newark, DE 19711.</span></text>
</content>
<name>title</name>
<script>on openCard
put "" into card field "return card" of card "help"
end openCard
on arrowKey choice
if choice is "right" then
visual wipe left to black
visual wipe left
end if
pass arrowKey
end arrowKey
</script>
</card>
card_5268.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">he C programming language has grown popular due to its simplicity, efficiency, and flexibility. C programs are often easily adapted to new environments. The recent ANSI C standard extends, standardizes, and makes consistent traditional C.
Symantec Corporation's* Think C 5.0 (henceforth called TC) includes an extension of ANSI C to support object-oriented programming (OOP) techniques. TC programs are organized according to the data structures of interest in the chosen application. Each data structure is encapsulated with the procedures acting upon the data to form an </span><span class="style7">object</span><span class="style3">. The features of inheritance (features of objects are easily "derived from" those of existing objects) and polymorphism (the procedures belonging to related objects may have the same names) are supported in TC. This organization promotes code reusability and maintainability, and allows great model consistency from the analysis through the implementation phases of the software engineering effort.
In contrast, conventional C programs are usually organized according to a procedural decomposition. A measure of object-orientation can be achieved in well-structured C programs by defining each data structure and the procedures which act upon it in </span></text>
</content>
<content>
<layer>background</layer>
<id>6</id>
<text>Preface</text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>5</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>Symantec Corp.
</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>10231
</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>Symantec Corp. - p13</text>
</content>
<name>preface</name>
<script></script>
</card>
card_9608.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text>an individual source file, using "static external" storage. However, the useful inheritance and polymorphism features cannot easily and consistently be duplicated.
The C++ language is a more detailed extension of C to further support modern structured programming techniques. In effect, TC is between ANSI C and C++. After learning TC the programmer can begin using C++ with little difficulty, and can learn the powerful added features of C++ at a later date if necessary. Note that by facilitating OOP, TC often allows simpler code than that produced using ANSI C. On the other hand some programmers find that the additional features provided by C++ add significant complexity to the elegant C language.
While TC is a unique language, the compatibility with ANSI C and the upward-compatibility with C++ lend TC programs the potential for a high degree of portability. If the Think Class Library is used to produce Macintosh-only applications, a measure of portability may be retained by careful characterization and isolation of the non-portable objects.*
</text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>6</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>62767</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>Portability via class libraries</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>Portability via class libraries - p234</text>
</content>
<name></name>
<script></script>
</card>
card_42626.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text>Most importantly, the Think C environment — with integrated editor, debugger, and class browser — is a powerful, productive, yet forgiving tool for software development on Macintosh computers. It is popular with both novice and professional programmers.
</text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>7</text>
</content>
<name></name>
<script></script>
</card>
card_10457.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
This document may be used to supplement an undergraduate course on Object-Oriented Programming techniques or C++. It differs from other textbooks by introducing TC/C++ for persons with no C programming experience, stressing OOP techniques and the most-used features of C. Persons with C background should study Ch. 1, 2.5, 3.1, 4, 7.2, 9, and Appendix 2.
Persons with no previous C experience may wish to supplement this material with a more extensive tutorial-style C text such as Lawrence Miller and Alexander Quilici's "Programming in C" (Wiley).* An excellent alternative for beginning programmers is Dave Mark's disk-based "Learn C on the Macintosh" (Addison-Wesley).*
The approach taken is practical and informal. Therefore, it is recommended that the reader supplement this material with a detailed reference of the ANSI-standard C language, such as the newest edition of Brian Kernighan and Dennis Ritchie's "The C Programming Language" (Prentice-Hall)*, as well as the TC manuals.
</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>Bibliography</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>Bibliography - p259</text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>8</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>2231</text>
</content>
<name></name>
<script></script>
</card>
card_10514.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text>Concepts of object-oriented programming are introduced here in the context of TC. An excellent text detailing OO concepts and their use is Grady Booch's "Object-Oriented Design" (Benjamin-Cummings).* Other resources include Peter Coad and Edward Yourdon's "Object-Oriented Analysis" (Prentice-Hall)* and Bertrand Meyer's "Object-Oriented Software Construction" (Prentice-Hall).* A reference-style source of features specific to C++ is Bjarne Stroustrup's "The C++ Programming Language" (Addison-Wesley).*
This document is not intended as a source for Macintosh programming techniques. That is, there is little discussion on the Macintosh Toolbox ROM routines nor on the event-oriented user-interaction model. An invaluable introduction to these issues is David Mark and Cartwright Reed's "Macintosh Programming Primer" (Addison- Wesley).*
Finally, the issue of using existing class libraries to simplify application design is discussed only in a simplified setting, with little regard for the Think Class Library provided with Think C. The reader should investigate the discussion in the Think
</text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>9</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>2231</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>Bibliography</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>Bibliography - p259</text>
</content>
<name></name>
<script></script>
</card>
card_48838.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
A HyperCard interface was chosen for this document because of the ease with which information may be cross-referenced, its ease of distribution, and because of the ability to provide source code in ready-to-use media. The use of footnotes for crossreferencing allows hardcopies of this HyperCard stack to retain all the information of the electronic version, with the exception of program listings given in scrolling text fields.
The text uses the Palatino 12 font, except for C code which is distinguished with Monaco 9.</span><span class="style4"> (This is Monaco 9.)</span><span class="style3">
Throughout the text an attempt will be made to indicate where ANSI C, Think C, and C++ differ. Statements made about C usually apply to TC and C++ as well, while statements about TC usually apply to C++. These relationships are summarized in Appendix 2. Appendix 1 briefly describes the TC development environment.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>11</text>
</content>
<name></name>
<script></script>
</card>
card_62122.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text>Chapter 1 introduces Think C and object-oriented programming with several preliminary definitions, a sample program showing the TC syntax, and a more detailed example showing the merits of the OOP approach.
Chapters 2 and 3 discuss C data types and functions, including sample programs.
Chapter 4 shows how these concepts are combined to construct TC/C++ classes, and includes a sample program.
Chapters 5, 6, 7, and 8 provide an overview of C operators, statements, preprocessor directives, and standard functions.
Chapter 9 suggests programming techniques which take advantage of TC/C++ constructs for improved maintainability and portability. This chapter contains code for producing simple graphics on Macintosh computers, with the potential for portability. It also includes a text-based application framework as a simplified example of sophisticated application frameworks such as the Think Class Library.
</text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>12</text>
</content>
<name></name>
<script></script>
</card>
card_10231.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
C was originally developed (in conjunction with the UNIX operating system) at AT&T Bell Laboratories in New Jersey in the late 1960's by Dennis Ritchie.
C++ was developed primarily by Bjarne Stroustrup at AT&T Bell Laboratories in the early 1980's.
Think C v. 5.0 and the Think Class Library are Macintosh-specific products of Symantec Corporation, 10201 Torre Avenue, Cupertino, CA 95014.
</text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>13</text>
</content>
<name></name>
<script></script>
</card>
card_19990.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
Sources consulted for this document included Brian Kernighan and Dennis Ritchie's "The C Programming Language" (Prentice-Hall), James Gardner's "From C to C: An Introduction to ANSI Standard C" (HBJ), Bjarne Stroustrup's "The C++ Programming Language" (Addison-Wesley), and the Think C 5.0 manuals.
Thanks to Dan Shafer for a practical and painless introduction to HyperTalk scripting.
Thanks to Maureen for everything.</text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>14</text>
</content>
<name></name>
<script></script>
</card>
card_7205.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">hink C 5.0 (TC) is an extension of the C programming language to support object-oriented programming (OOP). It is compatible with C++, which carries this extension further. This chapter provides sample TC/C++ programs which em- phasize the OOP approach. We will first define a few OOP terms and their use in TC.
An</span><span class="style6"> </span><span class="style7">object</span><span class="style3"> is a data structure combined — or </span><span class="style7">encapsulated</span><span class="style3"> — with the procedures which will act upon this data. The organization of this object is the object's </span><span class="style7">class</span><span class="style3">, or the type of the object. That is, a class definition lists the </span><span class="style7">instance variables</span><span class="style3"> (data) which are contained in all objects of this type, as well as the </span><span class="style7">methods</span><span class="style3"> (procedures), acting upon the data. In TC/C++, the definition for the </span><span class="style4">Person</span><span class="style3"> class may look like:
</span><span class="style4"> struct Person
{
int age;
int weight;
set();
print();
};</span></text>
</content>
<name></name>
<script></script>
</card>
card_10832.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">ny object which is defined with class </span><span class="style4">Person</span><span class="style3"> will contain integer instance variables representing age and weight. The only procedures which act on this data are: setting the values and printing the values. These methods may be defined by:
</span><span class="style4"> Person::set()
{
age = 28;
weight = 150;
}
Person::print()
{
printf("%d ",age);
printf("%d",weight);
}
</span><span class="style3">
(</span><span class="style4">printf()</span><span class="style3"> is a standard C library function discussed in the next section.)
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>16</text>
</content>
<name></name>
<script></script>
</card>
card_11123.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">o declare and allocate space for a </span><span class="style4">Person</span><span class="style3">-type object named </span><span class="style4">ralph</span><span class="style3">, we would write:
</span><span class="style4"> Person *ralph;
ralph = new(Person);
</span><span class="style3">
The first line defines a variable named </span><span class="style4">ralph</span><span class="style3"> which may contain the address of a </span><span class="style4">Person</span><span class="style3"> object, and the second line dynamically allocates space for a </span><span class="style4">Person</span><span class="style3"> object and places its address in the variable </span><span class="style4">ralph</span><span class="style3">. Using machine addresses like this is very common in C, and is discussed later in this chapter.
A method is invoked by sending the appropriate </span><span class="style7">message</span><span class="style3"> to the object. (This is identical to "calling a procedure" in a procedural language, but we will use the OOP terminology since this leads to a more natural understanding of the program.) To set and print </span><span class="style4">ralph</span><span class="style3">'s instance variables, we would send the messages:
</span><span class="style4"> ralph->set();
ralph->print();
</span><span class="style3">
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>17</text>
</content>
<name></name>
<script></script>
</card>
card_4342.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">he following page contains a complete TC/C++ program using the </span><span class="style4">Person</span><span class="style3"> class defined earlier. You can copy the program from the scrolling text field, paste it into a new source file called </span><span class="style18">person.c</span><span class="style3">, then compile* and run it. Note that one change must be made if you are using C++ instead of TC, as discussed below.
</span></text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>3295</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>Compiling TC applications</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>Compiling TC applications - p248</text>
</content>
<name>chapter 1</name>
<script></script>
</card>
card_29372.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">ample output is shown below, with the user's responses in <> braces.
</span><span class="style9"> Enter age and weight separated by spaces:
<35 175>
My age is 35
My weight is 175
</span><span class="style3">
Let's step through the code and discuss some new items. (You may wish to put a bookmark in the previous page so you can return to it easily. Click on its "book" icon.)
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>20</text>
</content>
<name></name>
<script></script>
</card>
card_12984.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
Everything between the </span><span class="style4">/*</span><span class="style3"> symbol and the </span><span class="style4">*/</span><span class="style3"> symbol is a </span><span class="style7">comment</span><span class="style3">, and is ignored by the compiler. A good C program should </span><span class="style7">not</span><span class="style3"> rely upon comments to impart its structure; however, it is good practice to identify the important parts of your source code and any unusual constructs.
An alternative syntax for comments is available in TC/C++: anything between the </span><span class="style4">//</span><span class="style3"> symbol and the end of a line is ignored.
The C compiler also ignores </span><span class="style7">white space</span><span class="style3"> such as blank lines and tabs, allowing the programmer to use his/her preferred formatting. Judicious use of white space helps improve the readability of the program.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>21</text>
</content>
<name></name>
<script></script>
</card>
card_11521.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
'</span><span class="style4"># include</span><span class="style3">' is a </span><span class="style7">preprocessor directive</span><span class="style3">, identified by the </span><span class="style4">#</span><span class="style3"> symbol. The C preprocessor carries out text-manipulation directives as a preliminary step to compilation. This one directs the preprocessor to "paste" the text from the indicated file into this file before compilation. The included file </span><span class="style18">stdio.h</span><span class="style3"> is called a </span><span class="style7">header</span><span class="style3"> file, and contains C source code declaring constants, data structures, and/or library functions which we will use in this program.
The C language is very terse, but is readily extended by the use of headers and function libraries.
</span></text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p223</text>
</content>
<name></name>
<script></script>
</card>
card_12751.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style4"> struct Person:indirect // for C++ omit ":indirect"
</span><span class="style3">
In C, the keyword </span><span class="style4">struct</span><span class="style3"> is used to define a new type of </span><span class="style7">data structure</span><span class="style3"> of the programmer's choice. That is, a variable defined with this new type can represent a collection (data record) of integer, character, and floating-point variables, called "members". This collection is described in a list enclosed by {} braces.
TC and C++ extend this idea so that the data structure may be a </span><span class="style7">class</span><span class="style3">. Objects defined with this type represent a collection of instance variables </span><span class="style7">and</span><span class="style3"> the methods — or "member functions" — which may act upon them. In this case, when an object of type </span><span class="style4">Person</span><span class="style3"> is defined later in the program, space will be allocated for two integer variables which may be accessed by sending set and print messages to the object.
The word </span><span class="style4">indirect</span><span class="style3"> is unique to TC, and specifies how TC should implement objects of class </span><span class="style4">Person</span><span class="style3">. The significance of this implementation will be discussed later.* To compile this program with C++, you omit the "</span><span class="style4">:indirect</span><span class="style3">".
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>23</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>38494</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>Macintosh memory management</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>Macintosh memory management - p158</text>
</content>
<name></name>
<script></script>
</card>
card_15137.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
These statements declare the instance variables </span><span class="style4">age</span><span class="style3"> and </span><span class="style4">weight</span><span class="style3"> to be of </span><span class="style7">type</span><span class="style3"> </span><span class="style4">int</span><span class="style3"> (integer). The remaining basic data types offered in C are </span><span class="style4">char</span><span class="style3"> (character) and </span><span class="style4">float</span><span class="style3"> (floating-point number), as well as larger and higher-precision kinds of integer and floating-point variables.
A note about usage in this document: a </span><span class="style7">definition</span><span class="style3"> is something which describes the structure of or allocates space for something, whereas a </span><span class="style7">declaration</span><span class="style3"> simply identifies the thing so the compiler is not confused. A </span><span class="style4">struct</span><span class="style3"> expression may be thought of as "declaring" the instance variables and methods of a class. However, although no space is yet allocated for a </span><span class="style4">Person</span><span class="style3"> object, the </span><span class="style4">struct</span><span class="style3"> expression "defines" the </span><span class="style4">Person</span><span class="style3"> class by describing its structure. (Definitions are usually implicitly declarations, while declarations need not define anything.)
Notice that a semicolon terminates simple C statements like the declaration "</span><span class="style4">int</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>24</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p202</text>
</content>
<name></name>
<script></script>
</card>
card_15503.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style4">ge;</span><span class="style3">'. A compound statement like a function body is enclosed by {} braces and is not followed by a semicolon.
However, the trailing semicolon </span><span class="style7">is</span><span class="style3"> required in the </span><span class="style4">struct</span><span class="style3"> declaration since its syntax requires an additional statement following the compound statement. In this case the statement is simply the "null" statement: a lone semicolon following the closing brace.
Also note that some programmers prefer an alternate bracket format which is treated identically by the compiler (since line feeds are ignored "white space"):
As mentioned above, class definitions in TC may declare what methods are members of the class. This declaration for the </span><span class="style4">set()</span><span class="style3"> method is a little different from the one used in the beginning of this chapter.* In C, all procedures are functions, which may </span><span class="style7">return</span><span class="style3"> a value upon completion. If we wish to declare a function which does not return a value, we say it returns </span><span class="style4">void</span><span class="style3">. The declaration for the </span><span class="style4">set()</span><span class="style3"> method also indicates that this function has no </span><span class="style7">arguments</span><span class="style3">; i.e., a </span><span class="style4">void</span><span class="style3"> argument. It is good practice to explicitly state the types of values accepted by and returned by C functions, to allow the compiler to enforce type-checking.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>26</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>7205</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>Previous declaration</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>Previous declaration - p15</text>
</content>
<name></name>
<script></script>
</card>
card_13426.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
This begins the definition for the </span><span class="style4">set()</span><span class="style3"> method, or member function. The </span><span class="style7">scope resolution operator</span><span class="style4"> :: </span><span class="style3">is required in order to indicate that this function is a member of the </span><span class="style4">Person</span><span class="style3"> class, as previously declared. (It is legal to have several functions with the same name as long as they are members of different classes.) Again, the types of the return value and of the formal parameters (none in this case) are given.
The function body is enclosed in {} braces, and assigns new values to the instance variables </span><span class="style4">age</span><span class="style3"> and </span><span class="style4">weight</span><span class="style3">.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>27</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p153</text>
</content>
<name></name>
<script></script>
</card>
card_17184.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
There are various combinations of </span><span class="style7">scope</span><span class="style3"> and </span><span class="style7">storage class</span><span class="style3"> for C variables. </span><span class="style7">automatic</span><span class="style3"> variables are those whose storage class is "dynamic": they are allocated upon entry to the function body in which they are declared and deallocated upon completion of the function. The scope of an automatic variable is the function in which it is defined (i.e., it is "local" to this function).
In a function body such as </span><span class="style4">Person::set()</span><span class="style3">, the automatic storage class is default, so "</span><span class="style4">int new_age</span><span class="style3">" is short for "</span><span class="style4">auto int new_age</span><span class="style3">". (Spaces are not permitted in variable or function names, so the underscore character </span><span class="style4">_</span><span class="style3"> is frequently used.) This declares </span><span class="style4">new_age</span><span class="style3"> to be a variable of type </span><span class="style4">int</span><span class="style3"> (integer) and also serves as a definition, allocating space for this variable. Automatic variables are not initialized in C, so we cannot generally count on </span><span class="style4">new_age</span><span class="style3"> to contain 0 — or even a legal value — until we've assigned it a value. (Actually, the default implementation of objects in Think C 5.0 causes their instance variables to be initialized to 0, but it is poor practice to count on
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>28</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p66</text>
</content>
<content>
<layer>background</layer>
<id>18</id>
<text>p59</text>
</content>
<name></name>
<script></script>
</card>
card_18361.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
Notice that the instance variables </span><span class="style4">age</span><span class="style3"> and </span><span class="style4">weight</span><span class="style3"> have </span><span class="style7">class</span><span class="style3"> scope and can be accessed directly from within the body of this member function even though they are neither formal parameters nor are they defined within the body of the function.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>29</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p64</text>
</content>
<content>
<layer>background</layer>
<id>18</id>
<text>p130</text>
</content>
<name></name>
<script></script>
</card>
card_16926.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style4"> printf("Enter age and weight separated by spaces:\n");
</span><span class="style3">
</span><span class="style4">printf()</span><span class="style3"> is a function defined in the ANSI library, for formatted output to the </span><span class="style7">standard output</span><span class="style3"> device — usually the screen. (On UNIX systems, </span><span class="style4">printf()</span><span class="style3"> output can be redirected to a file; this is done in TC using the </span><span class="style4">ccommand()</span><span class="style3"> library function.)
</span><span class="style4">printf()</span><span class="style3"> accepts a character string (actually an array of </span><span class="style4">char</span><span class="style3"> variables) as its first argument, optionally followed by additional arguments. The escape sequence '</span><span class="style4">\n</span><span class="style3">' in the character string tells C to begin a new line following this output.
Notice that all function calls in C are expressions which represent a value (or </span><span class="style4">void</span><span class="style3">). In fact, </span><span class="style4">printf()</span><span class="style3"> returns the number of characters successfully printed, but we are ignoring this value here.
If a function is used in a C source file, the compiler requires either a declaration or a definition of the function in the source file. The declaration for </span><span class="style4">printf()</span><span class="style3"> is con- tained in the file </span><span class="style18">stdio.h</span><span class="style3">, which was included into this file via the preprocessor.*
</span></text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>Header files</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>11521</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>Header files - p22</text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>30</text>
</content>
<name></name>
<script></script>
</card>
card_13648.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
Like </span><span class="style4">printf()</span><span class="style3">, </span><span class="style4">scanf()</span><span class="style3"> is defined in the ANSI library and declared in </span><span class="style18">stdio.h</span><span class="style3">. This function reads formatted values from the standard input device (usually the keyboard) and "returns" them as discussed below. Its syntax is similar to </span><span class="style4">printf()</span><span class="style3">'s: the first argument is a character string containing (only!) formatting characteristics. </span><span class="style4">%d</span><span class="style3"> indicates that an integer is expected from the input device. Following the string is a list of the variables associated with each format specifier.
C functions use </span><span class="style7">call by value</span><span class="style3"> rather than </span><span class="style7">call by reference</span><span class="style3">. This means that values passed as arguments to a function are assigned to the function's formal parameters, but any changes to the values of these formal parameters within the body of the called function do not affect the values of those variables in the calling function which were passed as arguments.
However, the above call to the </span><span class="style4">scanf()</span><span class="style3"> function </span><span class="style7">does</span><span class="style3"> change the values of </span><span class="style4">new_age</span><span class="style3"> and </span><span class="style4">new_weight</span><span class="style3"> in the calling function. The reason is that the </span><span class="style7">address</span><span class="style3"> of these </span></text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p223</text>
</content>
<name></name>
<script></script>
</card>
card_17666.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">ariables is passed, rather than their contents. This is accomplished with the </span><span class="style4">&</span><span class="style3"> ("address of") operator. The formal parameters of </span><span class="style4">scanf()</span><span class="style3"> now "point to" the </span><span class="style4">new_age</span><span class="style3"> and </span><span class="style4">new_weight</span><span class="style3"> variables defined in the </span><span class="style4">Person::set()</span><span class="style3"> function. </span><span class="style4">scanf()</span><span class="style3"> reads values from the standard input and assigns them to the variables "pointed to" by its parameters.
Incidentally, </span><span class="style4">scanf()</span><span class="style3"> also returns a value in the conventional sense: the number of items successfully read. As done here, it is common — but somewhat risky — to ignore this returned value.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>32</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p153</text>
</content>
<name></name>
<script></script>
</card>
card_18162.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
Here, the instance variables are assigned the values requested from the user in the foregoing </span><span class="style4">scanf()</span><span class="style3"> function call.
Interestingly, assignments are expressions in C, as are function calls. That is, the expression "</span><span class="style4">age = new_age</span><span class="style3">" has a value; namely, the value which was assigned. This means that assignments can be freely used within other expressions, such as "</span><span class="style4">weight = 4*(age = new_age)/7</span><span class="style3">".
Another important thing to notice is that we defined new automatic variables </span><span class="style4">new_age</span><span class="style3"> and </span><span class="style4">new_weight</span><span class="style3"> instead of simply passing </span><span class="style4">scanf()</span><span class="style3"> the addresses of the </span><span class="style4">age</span><span class="style3"> and </span><span class="style4">weight</span><span class="style3"> instance variables. For reasons discussed later, TC's management of objects makes it dangerous to pass the address of an instance variable as an argument to certain functions.* This is not the case with standard C++. That is, in C++ the program will work equally well if you use "</span><span class="style4">scanf("%d %d",&age,&weight)</span><span class="style3">".</span></text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>Macintosh memory management</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>Macintosh memory management - p158</text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>33</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>38494</text>
</content>
<name></name>
<script></script>
</card>
card_13900.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style4"> printf("My age is %d\n",age);
printf("My weight is %d\n",weight);
</span><span class="style3">
The </span><span class="style4">Person::print()</span><span class="style3"> method outputs the values of the instance variables.
As mentioned earlier, </span><span class="style4">printf()</span><span class="style3"> accepts a character string as its first argument, followed by an appropriate list of arguments. The characters </span><span class="style4">%d</span><span class="style3"> contained in the string specify that an integer value is to be printed in this location, in this case the value represented by the variable </span><span class="style4">age</span><span class="style3"> or the variable </span><span class="style4">weight</span><span class="style3">.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>34</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p215</text>
</content>
<name></name>
<script></script>
</card>
card_14229.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
Execution of a C program always begins with the function named </span><span class="style4">main()</span><span class="style3">. (This function, too, may have arguments passed to it. On UNIX systems the command line provides these arguments, and this is simulated with TC's </span><span class="style4">ccommand()</span><span class="style3"> library function.)
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>35</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p223</text>
</content>
<name></name>
<script></script>
</card>
card_14644.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
</span><span class="style3">C is case-sensitive, so it is legal to declare a variable — </span><span class="style4">person</span><span class="style3"> — of type </span><span class="style4">Person</span><span class="style3">. In this case, the </span><span class="style4">*</span><span class="style3"> ("that which is pointed to by") operator is used to indicate that person is a </span><span class="style7">pointer</span><span class="style3"> to a Person object. A pointer is a variable (usually using a long integer internal representation) which may contain the address of a value. Therefore, this declaration only allocates space for a machine address, </span><span class="style7">not</span><span class="style3"> a Person object or its instance variables. (In truth, the Macintosh implementation of an object is slightly different, but this will not concern us quite yet.*)
The </span><span class="style4">new</span><span class="style3"> operator allocates space for a </span><span class="style4">Person</span><span class="style3"> object (i.e., two integer instance variables plus "housekeeping" values used by TC) and returns the machine address where this newly-created object begins. The object may be accessed via the </span><span class="style4">person</span><span class="style3"> pointer as discussed below.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>36</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>Macintosh memory management</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>Macintosh memory management - p158</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>38494</text>
</content>
<name></name>
<script></script>
</card>
card_14948.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
</span><span class="style4">person</span><span class="style3"> is a pointer variable, containing the machine address of a </span><span class="style4">Person</span><span class="style3"> object. Although the prospect of accessing an object via its address may be daunting at first, TC/C++ handles all the "dirty work" for you.
The members — instance variables and methods — of an object pointed to by a pointer variable are accessed with the </span><span class="style4">-></span><span class="style3"> ("member of the object pointed to by") operator. Thus, "</span><span class="style4">person->print()</span><span class="style3">" calls the member function </span><span class="style4">print()</span><span class="style3"> of the </span><span class="style4">Person</span><span class="style3"> class, which operates upon the instance variables of the object pointed to by </span><span class="style4">person</span><span class="style3">. (For simplicity we'll refer to the </span><span class="style4">person</span><span class="style3"> pointer as though it were the object itself). Using OOP terminology, we are sending a </span><span class="style4">print</span><span class="style3"> message to the </span><span class="style4">person</span><span class="style3">. Note that if another variable </span><span class="style4">guy</span><span class="style3"> were declared pointing to another </span><span class="style4">Person</span><span class="style3"> object, then "guy-></span><span class="style4">print()</span><span class="style3">" would print the instance variables of this object rather than those of the </span><span class="style4">person</span><span class="style3">.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>37</text>
</content>
<content>
<layer>background</layer>
<id>18</id>
<text>p207</text>
</content>
<name></name>
<script></script>
</card>
card_14487.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">lthough it is possible to access the instance variables of an object directly using the </span><span class="style4">-></span><span class="style3"> notation, this is usually discouraged. Instead an object's instance variables should be accessed only by sending messages to the object, since this results in improved program </span><span class="style7">modularity</span><span class="style3">. This allows the programmer to later change the implementation of the instance variables without affecting the functions which access objects of this class. This in turn improves code maintainability and reusability, a goal of OOP languages.
Note that it is possible to modularize C programs even without TC/C++ style classes, by considering each source file to define a unique object whose instance variables have "file" scope. More significant advantages of the TC/C++ languages are developed in the next section.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>38</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>40401</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>public and private members</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>public and private members - p141</text>
</content>
<content>
<layer>background</layer>
<id>18</id>
<text>p207</text>
</content>
<name></name>
<script></script>
</card>
card_16112.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
As mentioned earlier, automatic variables are allocated and deallocated automatically when the function in which they are declared is entered and exited. This applies to the pointer variable </span><span class="style4">person</span><span class="style3">, as well. The space used by this variable to store the address of a </span><span class="style4">Person</span><span class="style3"> object is automatically deallocated when the main function ends.
However, the space occupied by the object itself (space for two integers plus the "housekeeping" values used by TC) is </span><span class="style7">not</span><span class="style3"> deallocated and therefore is not reclaimed in case the program needs it later. (Of course this is of little significance in this case since the entire program terminates when </span><span class="style4">main()</span><span class="style3"> terminates. Later we will define objects from within functions other than </span><span class="style4">main()</span><span class="style3">, and deallocation will be relevant.)
Since the </span><span class="style4">new</span><span class="style3"> operator was used to dynamically allocate a Person object, it is the programmer's responsibility to deallocate this space. This is accomplished with the </span><span class="style4">delete</span><span class="style3"> operator, whose operand should be a pointer to an object.</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>39</text>
</content>
<content>
<layer>background</layer>
<id>18</id>
<text>p207</text>
</content>
<name></name>
<script></script>
</card>
card_16467.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">his completes our look at the program listed in the source file </span><span class="style18">person.c</span><span class="style3">. We've introduced many features of C as well as the use of classes, objects, and messages provided by TC and C++. The next section extends this example to demonstrate some of the benefits these OOP constructs provide the programmer.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>40</text>
</content>
<content>
<layer>background</layer>
<id>18</id>
<text>p207</text>
</content>
<name></name>
<script></script>
</card>
card_2542.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">t this point, the reader may wonder why we haven't provided an instance variable of </span><span class="style4">Person</span><span class="style3"> which is a character string, to contain a person's name. Character strings are represented in C as arrays of </span><span class="style4">char</span><span class="style3"> variables. For simplicity, we will postpone discussion of how C handles arrays.* However, it should be noted that if the programmer later decides to implement such a feature in the </span><span class="style18">person.c</span><span class="style3"> program, no change will be required in the main() function. This is one of the benefits of modular program design, where the functions using an object are "shielded" from the implementation of the object and any changes thereto.
Of even greater significance is the ability to derive classes from existing classes in TC and C++. Derived classes </span><span class="style7">inherit</span><span class="style3"> the instance variables and methods of the "base" class, and may add new instance variables and methods. New methods may be defined with the same names as those in the base class, in which case they "override" the original methods. This property of </span><span class="style7">polymorphism</span><span class="style3"> means that the same messages can be sent to objects of different classes, with results appropriate to each.
The following program listing illustrates these concepts by deriving the </span><span class="style4">Student</span><span class="style3"> class </span></text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>Arrays, pointers, and strings</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>Arrays, pointers, and strings - p68</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>22415</text>
</content>
<name></name>
<script></script>
</card>
card_29918.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3"> TC/C++ program using the </span><span class="style4">Person</span><span class="style3"> and </span><span class="style4">Student</span><span class="style3"> classes:</span></text>
</content>
<content>
<layer>background</layer>
<id>6</id>
<text>Derivation of Student class from Person class</text>
</content>
<name></name>
<script></script>
</card>
card_16854.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">gain, you can copy this program from the scrolling text field and paste it into a new TC source file. Sample output is shown below, with the user's responses in <> braces.
Enter age and weight separated by spaces:
<12 67>
Enter student id number:
<45>
My age is 12
My weight is 67
My id number is 45
Notice that the only change to the </span><span class="style4">main()</span><span class="style3"> function is that the </span><span class="style4">person</span><span class="style3"> variable now points to a </span><span class="style4">Student</span><span class="style3"> object.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>44</text>
</content>
<name></name>
<script></script>
</card>
card_46824.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
</span><span class="style3">Only one minor change has been made to the definition of the </span><span class="style4">Person</span><span class="style3"> class.* The method declarations have been preceded by the </span><span class="style4">virtual</span><span class="style3"> keyword. For now we will assume that all methods will be declared as </span><span class="style4">virtual</span><span class="style3">.</span><span class="style4">
</span></text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>12751</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>Person definition</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>Person definition - p23</text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>45</text>
</content>
<name></name>
<script></script>
</card>
card_15831.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
A new class has been defined, called </span><span class="style4">Student</span><span class="style3">. The notation </span><span class="style4">Student:Person</span><span class="style3"> here indicates that the new class is </span><span class="style7">derived</span><span class="style3"> from the </span><span class="style4">Person</span><span class="style3"> class. (Since the </span><span class="style4">Person</span><span class="style3"> class was itself defined with the </span><span class="style4">indirect</span><span class="style3"> specifier, the derived class is also </span><span class="style4">indirect</span><span class="style3">.)
A derived class ("child", "descendant", "subclass") is one which inherits the instance variables and methods of its base class ("parent", "ancestor"). In this case, any object of type </span><span class="style4">Student</span><span class="style3"> will contain </span><span class="style4">age</span><span class="style3"> and </span><span class="style4">weight</span><span class="style3"> instance variables even if no such variables are explicitly declared in the definition of the </span><span class="style4">Student</span><span class="style3"> class. They are inherited from the </span><span class="style4">Person</span><span class="style3"> class.
Likewise, if no </span><span class="style4">set()</span><span class="style3"> or </span><span class="style4">print()</span><span class="style3"> methods are defined in the </span><span class="style4">Student</span><span class="style3"> class definition, a </span><span class="style4">Student</span><span class="style3"> object will still accept </span><span class="style4">set</span><span class="style3"> and </span><span class="style4">print</span><span class="style3"> messages by accessing the methods defined for the </span><span class="style4">Person</span><span class="style3"> class.</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>46</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p202</text>
</content>
<name></name>
<script></script>
</card>
card_19767.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text>As will be seen in Chapter 4, separate source files are often used for the definitions of each class. In this way there is no need to recompile the base class method definitions when a new class is derived from it.</text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>47</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p123</text>
</content>
<content>
<layer>background</layer>
<id>18</id>
<text>p116</text>
</content>
<name></name>
<script></script>
</card>
card_17427.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
The </span><span class="style4">Student</span><span class="style3"> class contains one additional instance variable, the </span><span class="style4">id_number</span><span class="style3">. Again, since </span><span class="style4">Student</span><span class="style3"> is derived from </span><span class="style4">Person</span><span class="style3">, </span><span class="style4">Student</span><span class="style3"> objects will have </span><span class="style4">age</span><span class="style3"> and </span><span class="style4">weight</span><span class="style3"> instance variables without need to redeclare them here.
Since the </span><span class="style4">set()</span><span class="style3"> and </span><span class="style4">print()</span><span class="style3"> methods are redeclared in the </span><span class="style4">Student</span><span class="style3"> definition, they "override" the </span><span class="style4">Person</span><span class="style3">'s definition of these methods, and will require new definitions. Since these methods were declared </span><span class="style4">virtual</span><span class="style3"> in the </span><span class="style4">Parent</span><span class="style3"> base class, it is not necessary to use the </span><span class="style4">virtual</span><span class="style3"> keyword here.
If these declarations had been ommitted, then objects of type </span><span class="style4">Student</span><span class="style3"> would still accept </span><span class="style4">set</span><span class="style3"> and </span><span class="style4">print</span><span class="style3"> messages but would use the definitions for these functions provided for the </span><span class="style4">Person</span><span class="style3"> class.</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>48</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p142</text>
</content>
<name></name>
<script></script>
</card>
card_18573.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
Notice that the overriding method must have the same type of arguments and return value as the original method, if the original method was declared </span><span class="style4">virtual</span><span class="style3">.
The </span><span class="style4">Student</span><span class="style3"> </span><span class="style4">set()</span><span class="style3"> method definition assigns the </span><span class="style4">id_number</span><span class="style3"> instance variable using the same approach as was used by the </span><span class="style4">Person</span><span class="style3"> </span><span class="style4">set()</span><span class="style3"> method to assign its instance variables. We could have assigned new values to the inherited </span><span class="style4">age</span><span class="style3"> and </span><span class="style4">weight</span><span class="style3"> instance variables in the same way. Instead we took the approach shown on the following page.</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>49</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p153</text>
</content>
<name></name>
<script></script>
</card>
card_18743.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
This syntax calls the </span><span class="style4">set()</span><span class="style3"> method of the </span><span class="style4">Person</span><span class="style3"> base class. When a </span><span class="style4">set</span><span class="style3"> message is sent to an object of type </span><span class="style4">Student</span><span class="style3">, the </span><span class="style4">id_number</span><span class="style3"> instance variable is assigned, and the </span><span class="style4">age</span><span class="style3"> and </span><span class="style4">weight</span><span class="style3"> instance variables are assigned according to the </span><span class="style4">set()</span><span class="style3"> method of the </span><span class="style4">Person</span><span class="style3"> class. A similar approach is used in </span><span class="style4">Student::print()</span><span class="style3">
The advantage of this approach is that future changes in the implementation of the </span><span class="style4">Person</span><span class="style3"> class will not require changes to the </span><span class="style4">Student</span><span class="style3"> class methods. For example, if a new </span><span class="style4">name</span><span class="style3"> instance variable is added to the </span><span class="style4">Person</span><span class="style3"> class, and this variable is assigned a value in </span><span class="style4">Person::set()</span><span class="style3">, then the </span><span class="style4">Student</span><span class="style3"> class will immediately inherit the new functionality.
In TC another approach available, and the programmer may instead use:
</span><span class="style4"> inherited::set();
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>50</text>
</content>
<content>
<layer>background</layer>
<id>18</id>
<text>p207</text>
</content>
<name></name>
<script></script>
</card>
card_19119.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
The sole change to the </span><span class="style4">main()</span><span class="style3"> function is the use of </span><span class="style4">new</span><span class="style3"> to create a </span><span class="style4">Student</span><span class="style3"> object instead of a </span><span class="style4">Person</span><span class="style3"> object. Notice that </span><span class="style4">person</span><span class="style3"> is still declared as a pointer to a </span><span class="style4">Person</span><span class="style3"> object. It is legal to assign a pointer of one class to a pointer declared to have another class, as long as the latter class is an </span><span class="style7">ancestor</span><span class="style3"> of the former.
When a </span><span class="style4">set</span><span class="style3"> or </span><span class="style4">print</span><span class="style3"> message is sent to the object pointed to by </span><span class="style4">person</span><span class="style3">, TC/C++ determines the class of this object and invokes the appropriate method. In this case, it is the </span><span class="style4">set()</span><span class="style3"> or </span><span class="style4">print()</span><span class="style3"> method of the </span><span class="style4">Student</span><span class="style3"> class which is invoked.
If these methods had </span><span class="style7">not</span><span class="style3"> been declared </span><span class="style4">virtual</span><span class="style3"> then the </span><span class="style4">Person</span><span class="style3"> methods would have instead been invoked. That is, the non-virtual method invoked depends on the type used to declare the </span><span class="style4">person</span><span class="style3"> pointer, rather than the type created at run-time.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>51</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p142</text>
</content>
<name></name>
<script></script>
</card>
card_63974.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">ater we will declare an array of </span><span class="style4">Person</span><span class="style3"> pointers, assign objects of various derived classes to these pointers, and make use of the polymorphism property of their virtual methods.</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>52</text>
</content>
<name></name>
<script></script>
</card>
card_19225.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text>In the previous sections we saw how modularizing a program according to the classes of its objects helps improve understanding and simplifies maintenance. Further, we saw how a derived class inherits the members of the original class, and how polymorphism allows the same messages to be sent to objects of either class.
The benefits of these OOP qualities to software engineering efforts should not be underestimated. If a change needs to be made to a piece of software in order to accomodate changing requirements, the traditional approach is to modify the original source code. This often requires the programmer to have a detailed understanding of the original functions and data structures.
In contrast, software designed with an OOP language like TC/C++ should require very few modifications of the original code in the new situation. The programmer instead defines new classes derived from the original classes, with the required additional functionality. The programmer is required to understand the sorts of messages the original objects responded to, not the implementation of the objects.
</text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>53</text>
</content>
<content>
<layer>background</layer>
<id>6</id>
<text>1.3 OOP Benefits</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p66</text>
</content>
<name></name>
<script></script>
</card>
card_19698.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text>This encourages the reuse of classes in new programming efforts, reducing duplication of effort and speeding development. As software engineering efforts become more and more complex (due in part to the demand for improved user interfaces and improved portability), OOP languages become indispensible to the programmer wishing to remain competitive. </text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>54</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p226</text>
</content>
<name></name>
<script></script>
</card>
card_6753.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">he C language was designed with a simple and minimal set of "built-in" data types, operators, and statements. However, C provides powerful tools to extend these facilities with user-defined data types, functions, and other constructs. In fact, C is commonly augmented with "libraries" of these facilities.
With the advent of Think C and C++, groups of data types and functions may be packaged together as </span><span class="style7">classes</span><span class="style3">, which will be discussed in Chapter 4. This new tool encourages further augmentation of C via class libraries.
This chapter will describe the use of the pre-defined data types available in C, user-defined data types, and arrays of these data types.
</span></text>
</content>
<name></name>
<script></script>
</card>
card_22558.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">nly 3 basic data types are available in C: </span><span class="style7">integers</span><span class="style3">, </span><span class="style7">characters</span><span class="style3">, and </span><span class="style7">floating point (real) numbers</span><span class="style3">. These types may be further specified according to the size or accuracy desired. Both </span><span class="style7">variables</span><span class="style3"> and </span><span class="style7">constants</span><span class="style3"> of these types may be defined.
The </span><span class="style7">identifier</span><span class="style3"> for a C variable — like that for a function — is any non-reserved sequence of letters (case is significant!), digits, and underscore (_) characters, with the restriction that the first character cannot be a digit and in general should not be an underscore. There is no restriction to the length of an identifier, although ANSI C compilers may ignore characters beyond the 31st. Commonly multi-word identifiers are described by using underscores (average_of_grades) to separate words or by beginning each new word with a capital letter (averageOfGrades). It is customary never to begin a variable identifier with a capital letter.
</span></text>
</content>
<name></name>
<script></script>
</card>
card_23387.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
Variables are declared by giving the </span><span class="style7">type specifier</span><span class="style3"> followed by the identifier. A statement declaring </span><span class="style4">average</span><span class="style3"> to identify an integer variable is:
</span><span class="style8">
</span><span class="style4"> int average;
</span><span class="style8">
</span><span class="style3">The </span><span class="style7">size</span><span class="style3"> of an integer is machine-dependent. The </span><span class="style4">int</span><span class="style3"> type specifier may be preceded or replaced by the keywords: </span><span class="style4">short</span><span class="style3">, </span><span class="style4">long</span><span class="style3">, or </span><span class="style4">unsigned</span><span class="style3">, to alter the storage. In TC, short ints and ints both occupy 16 bits (there's an option for 32 bit ints) and long ints occupy 32 bits. An unsigned int allows all 16 bits to be used for the magnitude of the number, allowing numbers from 0 to 65,535 (rather than plus or minus 32,767).
Integer constants are expressed as a sequence of digits with optional minus sign. A letter 'L' may be appended to indicate a long int constant:
</span><span class="style4">
long final_sum;
final_sum = 32768L;
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>57</text>
</content>
<name></name>
<script></script>
</card>
card_46372.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">his last statement demonstrates the C </span><span class="style7">assignment</span><span class="style3"> operator </span><span class="style4">=</span><span class="style3">. This operator assigns the value of its rightmost operand to the leftmost operand. Since </span><span class="style4">=</span><span class="style3"> is an operator, however, the assignment expression has a value of its own: </span><span class="style7">the value which was assigned</span><span class="style3">. Therefore in the following example the value of "</span><span class="style4">(a=6)</span><span class="style3">" is 6, so the value 12 is assigned to the integer variable </span><span class="style4">b</span><span class="style3">:
</span><span class="style4">
int a;
int b;
b = 2 * (a=6);
</span><span class="style3">In this example the variable </span><span class="style4">a</span><span class="style3"> is assigned the value 6 as a "side effect" of evaluating the expression "</span><span class="style4">2 * (a=6)</span><span class="style3">".</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>58</text>
</content>
<name></name>
<script></script>
</card>
card_23578.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
Floating-point variables are declared using the </span><span class="style4">float</span><span class="style3"> type specifier, and floating point constants are indicated by a decimal point:
</span><span class="style4">
float standard_deviation = 0.;
</span><span class="style3">Notice that an initial value may optionally be given in a declaration. In the absence of initialization, the variable will initially contain an unknown "garbage" value.
Double-precision floating-point variables use the </span><span class="style4">double</span><span class="style3"> specifier, usually occuping 64 bits instead of a float's 32 bits. Floating-point constants are double by default. In Think C, arithmetic using doubles is faster that that using float variables.
An alternate representation of floating-point constants uses "e" notation to indicate the number is to be multiplied by 10 raised to the indicated exponent:
</span><span class="style4">
standard_deviation = 1e-4; // same as .0001
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>59</text>
</content>
<name></name>
<script></script>
</card>
card_24002.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
Character variables are declared using the </span><span class="style4">char</span><span class="style3"> specifier, and may take on any single value in the machine's </span><span class="style7">character set</span><span class="style3">. An integer representation is used corresponding to this character set. Character constants may be identified by either the appropriate integer or by the character enclosed in single quotes:
</span><span class="style4">
char input1, input2;
input1 = 'a';
input2 = 97;
</span><span class="style3">(In machines using the ASCII character set, both </span><span class="style4">input1</span><span class="style3"> and </span><span class="style4">input2</span><span class="style3"> will represent the same value. In general, the first assignment is preferable since it is clearer and not machine-dependent.)
Non-printable characters in the character set are represented by an escape sequence: a backslash followed by a code character. For example, the carriage return character is represented by '</span><span class="style4">\n</span><span class="style3">'.</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>60</text>
</content>
<name></name>
<script></script>
</card>
card_24134.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">s suggested by the integer representation of characters, characters and integers may be (carefully!) mixed in expressions to accomplish certain tasks:
</span><span class="style4">
int i;
char c;
i = 12;
c = 'a' + i - 1;
</span><span class="style3">The above assigns</span><span class="style4"> c</span><span class="style3"> the character which occupies the (</span><span class="style4">i-1</span><span class="style3">)th position after the character </span><span class="style4">a</span><span class="style3"> in the machine's character set. In most character sets, and assuming </span><span class="style4">i</span><span class="style3"> is no greater than 26, </span><span class="style4">c</span><span class="style3"> will then represent the ith letter of the alphabet.
Character </span><span class="style7">strings</span><span class="style3"> are represented as arrays of characters in C. This will be discussed later in this chapter.</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>61</text>
</content>
<name></name>
<script></script>
</card>
card_70575.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
The </span><span class="style4">const</span><span class="style3"> qualifier indicates that a "variable" may not be modified. If an identifier is declared using the </span><span class="style4">const</span><span class="style3"> qualifier, an initial value must be given, and this value may not be changed subsequently. One use of this qualifier is to declare a symbolic constant:
</span><span class="style4">
const float pi = 3.14159;
.
.
pi = pi/2.; // disallowed since pi is constant
</span><span class="style3">Previous to the advent of </span><span class="style4">const</span><span class="style3">, symbolic constants were defined using the C preprocessor.*
Less frequently used, the </span><span class="style4">volatile</span><span class="style3"> qualifier indicates that a value may change without any action on the part of the program, perhaps via intervention by the operating system. When a variable is declared </span><span class="style4">volatile</span><span class="style3">, the compiler disallows the </span></text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>51878</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>Macro substitution</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>Macro substitution - p192</text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>62</text>
</content>
<name></name>
<script></script>
</card>
card_73425.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">he value of a </span><span class="style7">pointer</span><span class="style3"> variable is the </span><span class="style7">address</span><span class="style3"> of a value of another type. In this case, the type of value contained at this address must be stated. The </span><span class="style4">*</span><span class="style3"> qualifier used here declares the variable </span><span class="style4">f_ptr</span><span class="style3"> to be a pointer to a floating-point value:
</span><span class="style4">
float *f_ptr;
</span><span class="style3">Whenever a pointer variable is used, a non-pointer value must be declared as well, in order to allocate machine addresses to contain the data to be pointed to. Two operators are commonly used in expressions involving pointers: </span><span class="style4">&</span><span class="style3"> ("address of") and </span><span class="style4">*</span><span class="style3"> ("that which is pointed to by").
</span><span class="style4">
float amplitude = 100.;
float *f_ptr;
f_ptr = &litude;
amplitude = *f_ptr/2.;
</span><span class="style3">These statements declare a pointer </span><span class="style4">f_ptr</span><span class="style3"> to a float, as well as a float </span><span class="style4">amplitude</span><span class="style3"> which is initialized here to 100.
</span></text>
</content>
<name></name>
<script></script>
</card>
card_24451.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">The address of" the variable </span><span class="style4">amplitude</span><span class="style3"> is assigned to </span><span class="style4">f_ptr</span><span class="style3">. Finally, "that which is pointed to by" </span><span class="style4">f_ptr</span><span class="style3"> (namely the value represented by </span><span class="style4">amplitude</span><span class="style3">) is halved and assigned back to </span><span class="style4">amplitude</span><span class="style3">.
Pointers are used frequently in C, mainly for two purposes: informing a function of the location of data to be accessed and traversing arrays efficiently. (Note that the former purpose essentially extends the scope* of the data. Abuse of this may produce code which is difficult to understand and to maintain.)
A special pointer, the </span><span class="style7">void pointer</span><span class="style3"> will be useful later in this document. The </span><span class="style4">void</span><span class="style3"> data type is used mostly to declare the return value of functions whose return value is to be ignored. Variables cannot be declared to have this type. However, variables which are void pointers may be declared. Such variables may be assigned pointers of </span><span class="style7">any</span><span class="style3"> other type:
</span><span class="style4">
float f = 100.;
void *v_ptr;
v_ptr = &f;
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>65</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>20338
</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>Scope of variables</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>Scope of variables - p84</text>
</content>
<name></name>
<script></script>
</card>
card_75861.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
The </span><span class="style4">const</span><span class="style3"> qualifer* may be applied to pointer variables in two ways. The pointer itself may be declared constant, in which case it may not subsequently be set to point to a different location. Alternately (or in addition), the pointer may be declared as pointing to an unchangeable value. These are illustrated below:
</span><span class="style4">
float pi = 3.14159,
e = 2.71828;
float *const ptr1 = π
const float *ptr2 = π
*ptr1 = 3.; // ok, changes value of pi to 3.
ptr1 = &e; // disallowed since ptr1 is constant
ptr2 = &e; // ok, ptr2 now points to e
*ptr2 = 3.; // disallowed: can't change value through ptr2
</span><span class="style3">
</span></text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>70575</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>const qualifier</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>const qualifier - p62</text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>66</text>
</content>
<name></name>
<script></script>
</card>
card_69591.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
The numerical address used to store a value is generally of little interest to the programmer. However, a special pointer constant is used by many functions which deal with pointers: the </span><span class="style4">NULL</span><span class="style3"> pointer. </span><span class="style4">NULL</span><span class="style3"> is a symbolic constant* declared in the system header file** </span><span class="style18">stddef.h</span><span class="style3"> (and often other headers as well). It represents the zero address — C guarantees that no data will validly have this address. Therefore, </span><span class="style4">NULL</span><span class="style3"> is usually used to signify an abnormal event, or to initialize pointer variables to an "unused" state. For example,
</span><span class="style4">
# include <stddef.h>
.
.
if (f_ptr != NULL)
amplitude = *f_ptr;</span></text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>51878
52189</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>Macro substitution
File inclusion</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>Macro substitution - p192</text>
</content>
<content>
<layer>background</layer>
<id>23</id>
<text>File inclusion - p199</text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>67</text>
</content>
<name></name>
<script></script>
</card>
card_22415.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">n </span><span class="style7">array</span><span class="style3"> is a sequence of values of a given data type, arranged contiguously in memory. Arrays are declared by following the identifier with an integer constant enclosed in [] brackets. To declare an array of 10 floats requires:
</span><span class="style4">
float f_array[10];
</span><span class="style3">Individual </span><span class="style7">elements</span><span class="style3"> of an array are accessed using the index in brackets. Indexing begins at 0, so in the above example, elements </span><span class="style4">f_array[0]</span><span class="style3"> through </span><span class="style4">f_array[9]</span><span class="style3"> are allocated appropriately, but </span><span class="style4">f_array[10]</span><span class="style3"> should not be accessed.
</span><span class="style4">
f_array[5] = 100.;
</span><span class="style3">Multi-dimensional arrays are declared using the following syntax:
</span><span class="style4">
float f_array[10] [10];
</span><span class="style3">This declares a 10 by 10 array. The indexing begins with 0 for both rows and columns.</span></text>
</content>
<content>
<layer>background</layer>
<id>6</id>
<text>2.3 Arrays</text>
</content>
<name></name>
<script></script>
</card>
card_24803.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
Like characters, pointers can be (carefully!) mixed with integer values in expressions. A pointer represents a machine address, which is itself a (usually long) integer. However, C simplifies pointer arithmetic by making use of the known size of the data type pointed to by the pointer. Thus, if </span><span class="style4">f_ptr</span><span class="style3"> is declared as a pointer to a floating-point value on a machine where each float requires 4 machine addresses, then (</span><span class="style4">f_ptr + 1</span><span class="style3">) points 4 machine addresses beyond </span><span class="style4">f_ptr</span><span class="style3">.
Since arrays are stored contiguously, this means that if a pointer represents the address of an element of the array, then incrementing the pointer will cause it to point to the next element of the array, regardless of the type of the array. The following assigns the value 100 to element 6 of the array:
</span><span class="style4">
float *f_ptr;
float f_array[10];
f_ptr = &f_array[5];
*(f_ptr+1) = 100.;</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>69</text>
</content>
<name></name>
<script></script>
</card>
card_25001.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">n fact, the identifier of the array is itself treated as a pointer to the zeroth element of the array (remember array indexing begins with 0). The following are equivalent:
</span><span class="style4">
f_array and &f_array[0]
f_array+1 and &f_array[1]
*(f_array+1) and f_array[1]
</span><span class="style3">That is, the syntax: </span><span class="style4">name[i]</span><span class="style3"> is treated the same as: </span><span class="style4">*(name+i)</span><span class="style3"> in C. If </span><span class="style4">f_ptr</span><span class="style3"> contains the address of </span><span class="style4">f_array[5]</span><span class="style3">, then the following are equivalent:
</span><span class="style4">
f_ptr[1] and f_array[6]
</span><span class="style3">However, an important distinction between an array identifier and a true pointer variable is that the former is a constant address, and cannot have a new value assigned to it:
</span><span class="style4">
f_array = f_ptr; // disallowed, since f_array is a pointer constant,
// not variable
</span><span class="style3">
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>70</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p66</text>
</content>
<name></name>
<script></script>
</card>
card_27221.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
A character string constant is a sequence of characters enclosed in double quotes, and represents an array of character values. The last element of the array is the non-printable "null" character: '</span><span class="style4">\0</span><span class="style3">', supplied automatically in string constants. A string constant is treated by C syntactically as the name of a character array, which itself is a pointer to the zeroth element of the array. Thus the following assigns the address of the zeroth element of the string "Hello, world!" to </span><span class="style4">c_ptr</span><span class="style3">:
</span><span class="style4">
char *c_ptr;
c_ptr = "Hello, world!";
</span><span class="style3">The elements of this string may be accessed using either array indexing: </span><span class="style4">c_ptr[4]</span><span class="style3">, or pointer arithmetic: </span><span class="style4">*(c_ptr+4)</span><span class="style3">. It is important to note that the string defined above is a constant value and ANSI C disallows assignments which change it:
</span><span class="style4">
c_ptr[4] = 'x'; // disallowed in this case, since "Hello, world!"
// is a constant
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>72</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p66</text>
</content>
<name></name>
<script></script>
</card>
card_25644.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">ecall that while the name of an array can be thought of as a pointer, it is also a constant and cannot have a new address assigned to it. Therefore the following is also disallowed:
</span><span class="style4">
char c_array[14];
c_array = "Hello, world!"; // disallowed since c_array is a constant
</span><span class="style3">C does not provide built-in operators for manipulating arrays. Fortunately, functions to perform string manipulation are included in the standard C function libraries, which — when linked together with the programmer's own code — serve to extend the C language. The </span><span class="style4">strcpy()</span><span class="style3"> function takes two character array name (i.e. character pointer) arguments and copies the elements of the second array to those of the first. It does </span><span class="style7">not</span><span class="style3"> simply copy the second pointer to the first. </span><span class="style4">strcpy()</span><span class="style3"> requires that the second array contain a terminating null character '</span><span class="style4">\0</span><span class="style3">'. (Note that </span><span class="style4">c_array</span><span class="style3"> allocates 14 elements to accomodate the extra character.)
</span><span class="style4">
char c_array[14];
strcpy(c_array,"Hello, world!"); // must '#include <string.h>'
</span><span class="style3">
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>73</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p66</text>
</content>
<name></name>
<script></script>
</card>
card_20884.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3"> provides the facility to create several kinds of custom data types. Arrays of and pointers to custom data types are also permitted, using identical syntax to that for ordinary int, float, and char variables. In effect, a consistent extension to the C language is thus defined.
Defining any of the custom types is usually done with the following syntax:
</span><span class="style4">
<kind of custom type> <name given to custom type>
{
<list of members of custom type>
.
.
};
</span><span class="style3">(The trailing semicolon , or "null" statement, is required. The syntax requires a statement to follow the closing bracket. Occasionaly the programmer will place an identifier before the semicolon to declare a variable of the new type immediately.)
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>74</text>
</content>
<name></name>
<script></script>
</card>
card_25150.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
The most useful kind of custom data type is the structure, or record. The structure groups several different data types together so they may be manipulated using a single name. A structure representing a personnel record may look like:
</span><span class="style4">
struct personnel_rec
{
char name[80];
int id_number;
float salary;
};
</span><span class="style3">The name, or </span><span class="style7">tag</span><span class="style3">, of this new data type follows identifier naming rules.* (Some programmers capitalize the first or all letters of the tag.) Although the foregoing defines the new data type, it does not yet allocate space for a variable having this type. A new variable named </span><span class="style4">jack</span><span class="style3"> is declared using:
</span><span class="style4">
struct personnel_rec jack;
</span><span class="style3">
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>75</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>22558</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>Identifier naming conventions</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>Identifier naming conventions - p56</text>
</content>
<name></name>
<script></script>
</card>
card_26007.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">ndividual members of this structure variable are accessed using the </span><span class="style7">dot</span><span class="style3"> (</span><span class="style4">.</span><span class="style3">) operator:
</span><span class="style4">
strcpy(jack.name,"Jack Nicklaus");
jack.id_number = 12345;
jack.salary = 1.4e6;
</span><span class="style3">Structure variables may be used in the same way as variables of the basic data types. The programmer can declare an array of structure variables, assign a variable to another variable of the same type, pass a structure variable to an appropriately-defined function, etc.
</span><span class="style4">
struct personnel_rec person[10];
strcpy(person[0].name,"John Doe");
person[0].id_number = 999;
person[0].salary = 30000.;
person[1] = person[0];</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>76</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p202</text>
</content>
<name></name>
<script></script>
</card>
card_26199.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">requently pointers are used to structure variables. A special operator </span><span class="style4">-></span><span class="style3"> is used in place of the dot operator to access members of a structure pointed to by a pointer variable, to avoid cumbersome syntax. It is important to remember to define a non-pointer variable as well in order to allocate space for the structure itself:
</span><span class="style4">
struct personnel_rec *person_ptr,
jack;
person_ptr = &jack; // if you forget this you may crash the program!
person_ptr->salary = 1.5e6; // same as: (*person_ptr).salary = 1.5e6
</span><span class="style3">The same array-pointer relationship holds as that for the basic data types.
</span><span class="style4">
struct personnel_rec person[10];
(person+1)->salary = 1.5e6; // ok since space is allocated above
</span><span class="style3">It is illegal to declare a member of a struct to be a variable of the same user-defined type. For example, a </span><span class="style4">personnel_rec</span><span class="style3"> variable may not be a member of the </span><span class="style4">personnel_rec</span><span class="style3"> type, for obvious reasons. However, it is legal to declare a member to
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>77</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p202</text>
</content>
<name></name>
<script></script>
</card>
card_33145.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">e a pointer to a variable of the same type. For example, a variable of type "</span><span class="style4">struct personnel_rec*</span><span class="style3">" may be a member of the </span><span class="style4">personnel_rec</span><span class="style3"> type. Moreover, member variables may be declared to be of another user-defined type, such as a union or enum type, as discussed in the following pages.
Think C and C++ extend C's struct declaration to support object-oriented programming techniques, as discussed in Chapter 4.</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>78</text>
</content>
<content>
<layer>background</layer>
<id>18</id>
<text>p207</text>
</content>
<name></name>
<script></script>
</card>
card_26498.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
Typedef declarations simply allow the programmer to define synonyms for commonly-used data types. (Again, these synonyms must follow identifier naming rules.* Some programmers capitalize the first or all letters in the synonym.) For example, if the programmer wants to define variables which take on integer values but which are treated as boolean variables (only 0 or 1 allowed) in his/her own code, the following declaration may be used:
</span><span class="style4">
typedef int boolean; // just do this once, at top of file
boolean success; // success is actually an int variable
</span><span class="style3">If pointers to </span><span class="style4">personnel_rec</span><span class="style3"> structures are used frequently, the following may be used:
</span><span class="style4">
typedef struct personnel_rec* pr_ptr; // do this once, at top of file
pr_ptr person; // same as: struct personnel_rec *person </span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>79</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>22558</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>Identifier naming conventions</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>Identifier naming conventions - p56</text>
</content>
<name></name>
<script></script>
</card>
card_27786.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
The syntax for defining and using unions is identical to that for structs.
</span><span class="style4">
union input_value
{
int i;
float f;
};
</span><span class="style3">Unlike a struct, however, declaring a variable of this type allocates space for only the </span><span class="style7">largest</span><span class="style3"> member in the union. When a value is assigned to one of the members, any value formerly associated with another member is lost; that is, only one member contains a value at a time. This property is useful when the programmer would like to define a variable which can take on values of different types at different points in his/her program.</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>80</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p202</text>
</content>
<name></name>
<script></script>
</card>
card_27938.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">he following declares a variable of type "</span><span class="style4">union input_value</span><span class="style3">", and assigns values to it.
</span><span class="style4">
union input_value response;
response.i = 7;
response.f = 100.; // the value of response.i is now lost
</span><span class="style3">Following the assignment to member </span><span class="style4">f</span><span class="style3">, the value assigned to member </span><span class="style4">i</span><span class="style3"> is no longer available, since the space allocated for it is shared by member </span><span class="style4">f</span><span class="style3">.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>81</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p142</text>
</content>
<name></name>
<script></script>
</card>
card_26884.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
An enumeration type is used to define a variable which can take on only one of a set of values, to improve program clarity. A comma-separated list of identifiers for these values is given. These identifiers are internally treated as integer constants representing their position in the list, starting with 0. The list is </span><span class="style7">not</span><span class="style3"> terminated with a semicolon.
<text><span class="style3">ow the only values which should be assigned to this variable are the enumerated values: </span><span class="style4">Monday</span><span class="style3">, </span><span class="style4">Tuesday</span><span class="style3">, etc.
</span><span class="style4">
today = Tuesday;
today = 1; // discouraged
</span><span class="style3">Although the enumerated values are internally represented as integers, the second assignment above defeats the purpose of the enum type. However, it is occasionally useful to mix enum variables and integers in expressions.</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>83</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p142</text>
</content>
<name></name>
<script></script>
</card>
card_20338.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3"> programs consist of one or more </span><span class="style7">source files</span><span class="style3"> which contain the programmer's C source code. These are linked together after compilation to produce the executable program.
The </span><span class="style7">scope</span><span class="style3"> of an identifier (user-defined type name, variable name, or function name) is the area of the source code from which the identifier can be accessed. A variable's </span><span class="style7">storage class</span><span class="style3"> determines the allocation and deallocation of space for the variable.
There are 2 important scopes for identifiers in ANSI C. An identifier with </span><span class="style7">block</span><span class="style3"> scope is "visible" only within the body of the function in which it is declared (a "local" identifier). An identifier having </span><span class="style7">file</span><span class="style3"> scope must be declared outside of the body of any function in the source file, and can be accessed from any place in the file following where it is declared (a "global" identifier).
For example, the name (or "tag") for a user-defined data type may be defined at the beginning of a source file (file scope) so that it can be used to define variables of this
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>84</text>
</content>
<content>
<layer>background</layer>
<id>6</id>
<text>2.5 Scope & Storage Class</text>
</content>
<name></name>
<script></script>
</card>
card_7805.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">ype within any function later in the source file.
On the other hand, variables declared within a function body have block scope and do not conflict with variables having the same names but which are declared in other functions. It is generally regarded as good practice to avoid declaring variables with file scope, to prevent confusion with like-named variables having block scope and to clarify the relationships among functions. Rather, variables which are used by more than one function should be passed as function arguments wherever practical.
Unless declared </span><span class="style4">static</span><span class="style3"> (discussed later), an identifier with file scope is also available from within other source files, although it should be redeclared in each as discussed below. Header files* are commonly used for the purpose of listing declarations of those identifiers which will be used in several source files.
Think C and C++ add a third scope — </span><span class="style7">class</span><span class="style3"> — applying to the instance variables of a user-defined class, as discussed in Chapter 4.
</span></text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>52189</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>File inclusion</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>File inclusion - p199</text>
</content>
<name></name>
<script></script>
</card>
card_28174.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">efore discussing storage classes, we should distinguish between the terms </span><span class="style7">delcaration</span><span class="style3"> and </span><span class="style7">definition</span><span class="style3"> as used in this document. A definition is something which describes the structure of or allocates space for something, whereas a declaration simply identifies the thing so the compiler is not confused. The </span><span class="style4">personnel_rec</span><span class="style3"> struct expression discussed earlier* may be thought of as "declaring" the types of its members, since no space is yet allocated for these variables. However, we say the struct expression "defines" the new </span><span class="style4">personnel_rec</span><span class="style3"> type by describing its structure.
When a variable is declared in the body of a function (block scope), it has the </span><span class="style7">automatic</span><span class="style3"> storage class by default. Space for such a variable is automatically allocated upon declaration — meaning that the declaration also serves as a definition — and deallocated upon exit from this function. If the function is called again at a later time, the value contained in this variable is generally </span><span class="style7">not</span><span class="style3"> the value remaining after the previous call. (The declarations of some automatic variables may be preceded with the </span><span class="style4">register</span><span class="style3"> specifier. This may speed access by using one of the machine's high-speed registers instead of standard memory. The number of registers available</span></text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>25150</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>personnel_rec structure</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>personnel_rec structure - p75</text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>86</text>
</content>
<name></name>
<script></script>
</card>
card_28465.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">nd the data types allowed are machine-dependent. Standard memory will be used if no appropriate register is available.)
When a variable is declared outside the body of a function (file scope), it has the </span><span class="style7">static</span><span class="style3"> storage class by default. Space for such a variable is allocated at the start of the program's execution, and is deallocated upon the program's termination. As
mentioned earlier, this variable may be accessed from within other source files provided these source files redeclare the variable. Since space for the variable must be allocated only once, the declaration in one and only one of the source files should also serve as a definition for the variable. This is accomplished in one of two ways in ANSI C. (1) The (sole) definition is of the form "</span><span class="style4">int id_number</span><span class="style3">" and the declarations in other files are of the form "</span><span class="style4">extern int id_number</span><span class="style3">". (2) The (sole) definition involves an initialization as "</span><span class="style4">extern int id_number = 0</span><span class="style3">" and the declarations in other files are of the form "</span><span class="style4">extern int id_number</span><span class="style3">".
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>87</text>
</content>
<name></name>
<script></script>
</card>
card_28872.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">lthough function definitions do not allocate space as variable definitions do, a distinction is still made between the function definition and a declaration of this entity. Functions are defined in a single source file, and the function "prototype" is used to declare the function for access in other source files.*
Since the "definition" of a user-defined data type includes declarations needed by the compiler, it must be included in every source file using the data type. As mentioned earlier, header files are usually used to avoid repetition.**
It is possible to override the default storage class for local variables (automatic) by using the </span><span class="style4">static</span><span class="style3"> storage class specifier:
</span><span class="style4">
static int cumulative_sum;
</span><span class="style3">Such a variable retains its previous value during subsequent function calls. If an initialization is provided, it is assigned only the first time the function is called.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>88</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>31005
52189</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>Function scopes
File inclusion</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>Function scopes - p103</text>
</content>
<content>
<layer>background</layer>
<id>23</id>
<text>File inclusion - p199</text>
</content>
<name></name>
<script></script>
</card>
card_29148.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">onfusingly, the </span><span class="style4">static</span><span class="style3"> specifier can also be applied to identifiers (variables, functions, type definitions) having file scope. In this case, the storage class is not affected (since such variables are always static and functions and type definitions have no storage class) but it is no longer possible to access the identifier from other source files. (In effect, the scope has been restricted to a single file only.)
This technique is often useful to organize a program into several source files, each of which has a restricted and well-defined interface with the other source files. An alternative approach for obtaining such modularity is provided by the object-oriented features of TC and C++ discussed in Chapter 4.
TC/C++ adds a third storage class termed </span><span class="style7">free</span><span class="style3"> storage. Allocation and deallocation of free-store variables occurs at points defined by the programmer, without regard for function boundaries. This ability is also available to C programmers via the standard library functions malloc() and free(), but not as part of the language definition.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>89</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p223</text>
</content>
<name></name>
<script></script>
</card>
card_64457.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">he </span><span class="style4">new</span><span class="style3"> operator in TC/C++ returns a pointer to a block of memory large enough to accomodate the desired type, or the </span><span class="style4">NULL</span><span class="style3"> pointer if memory is unavailable. The </span><span class="style4">delete</span><span class="style3"> operator deallocates the space pointed to by the pointer.
</span><span class="style4">
struct personnel_rec *jack;
jack = new struct personnel_rec; // allocate a personnel_rec
.
.
delete jack;
</span><span class="style3">In Think C, these operators can only be applied to "class" types (Chapter 4).
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>90</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p215</text>
</content>
<name></name>
<script></script>
</card>
card_22999.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">he following page contains a complete C program demonstrating the creation of enum and struct data types. The code may be copied from the scrolling text field, pasted into a new source file </span><span class="style18">personnel.c</span><span class="style3">, and compiled.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>91</text>
</content>
<name></name>
<script></script>
</card>
card_29601.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text>In C there is no syntactic distinction between procedures and functions. A procedure is simply a function which does not return a useful value. Traditionally C programs were constructed by decomposing the overall task into a hierarchy of functions and procedures.
As will be discussed in Chapter 4, Think C and C++ provide features which encourage the object-oriented programming approach, where the overall task is decomposed instead into a collection of interacting objects, each of which encapsulates data and the procedures — or "member functions" — which act upon this data.
An understanding of C functions is required before the programmer can construct objects, and traditional C functions also find uses in such programs.</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p215</text>
</content>
<name></name>
<script></script>
</card>
card_12248.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">he definition for an ANSI C function begins with a </span><span class="style7">function prototype</span><span class="style3">. This heading gives the function name and declares the types of the </span><span class="style7">formal parameters</span><span class="style3"> and the type of the </span><span class="style7">return value</span><span class="style3"> of the function, if any. The function syntax is:
</span><span class="style4">
<type of return value> <function name> (<parameter declarations>)
{
<function body>
.
.
}
</span><span class="style3">Note there is no trailing semicolon following either the prototype or the function body.
Also note that pre-ANSI C functions list the parameters following the function name in the heading, but declare the types of these parameters in additional statements between the heading and the left bracket beginning the function body.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>94</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p210</text>
</content>
<name></name>
<script></script>
</card>
card_16372.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">he </span><span class="style4">return</span><span class="style3"> statement causes the function to terminate, and indicates the return value.
The parameters of the function (in this case the variable </span><span class="style4">x</span><span class="style3">) have the same scope and storage class as automatic variables: they are only visible in the function body and they are allocated and deallocated upon entry to and exit from the function.
If the function does not require any formal parameters, the word </span><span class="style4">void</span><span class="style3"> should be used in place of its parameter list. (In pre-ANSI C, the list is simply left empty.) Likewise, if the function does not return a value its return type is declared as </span><span class="style4">void</span><span class="style3">. For example:
</span><span class="style4">
void say_hello(void)
{
printf("Hello!\n");
return; // may be omitted in this case
}
</span><span class="style3">
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>96</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p215</text>
</content>
<name></name>
<script></script>
</card>
card_26691.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">n either ANSI C or pre-ANSI C, the </span><span class="style4">square()</span><span class="style3"> function is </span><span class="style7">called</span><span class="style3"> (evaluated) from another function by providing an </span><span class="style7">argument</span><span class="style3"> in parentheses:
</span><span class="style4">
new_value = square(old_value);
</span><span class="style3">C functions are </span><span class="style7">call by value</span><span class="style3">, meaning the value passed to the function as its argument is assigned to the corresponding formal parameter when the function is called. Any changes to the value of this formal parameter do </span><span class="style7">not</span><span class="style3"> affect the value of the argument used for the function call. In the above example, if the </span><span class="style4">square()</span><span class="style3"> function had assigned a new value to its parameter </span><span class="style4">x</span><span class="style3">, the value of the variable </span><span class="style4">old_value</span><span class="style3"> in the calling function would remain unchanged.
C function calls are expressions, whose value is the value specified in the function's return statement, if any. The above example assigns the value of the function call expression to the variable </span><span class="style4">new_value</span><span class="style3">; however, the function call could as well appear anywhere a C expression is allowed. For example:
</span><span class="style4">
new_value = square(square(old_value)/2.);
</span></text>
</content>
<content>
<layer>background</layer>
<id>6</id>
<text>3.2 Function Calls</text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>97</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p142</text>
</content>
<name></name>
<script></script>
</card>
card_30821.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">ften a function will return a value but the calling function will choose to ignore this value. For example the standard library function </span><span class="style4">printf()</span><span class="style3"> prints its argument and returns the number of characters printed:
</span><span class="style4">
printf("Hello\n"); // return value ignored
</span><span class="style3">If a function returns a void value, the above syntax should always be used, since void values cannot be used in other expressions.</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>98</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p223</text>
</content>
<name></name>
<script></script>
</card>
card_31791.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
Since a function cannot alter the value of a variable which is passed as an argument, it may appear that the only way for a function to communicate with its calling function is via the return value. Another way of establishing communication between functions is through global variables (variables with file scope). However, the use of global variables can cause code to be difficult to debug and maintain.
A technique commonly used in C programs is to declare a formal parameter of the function to be a pointer variable.* The calling program passes the address of a variable (using the </span><span class="style4">&</span><span class="style3"> operator) as an argument to the function. The called function may assign a new value to the variable "pointed to" by its pointer parameter, thus altering the value of a variable in the calling function.
In effect, the block scope of the calling function's variable is subverted by making the variable accessible from within another function's body. However, this is considered less problematic than the use of global variables since the scope boundaries remain </span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>99</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>20555</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>Pointer variables</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>Pointer variables - p64</text>
</content>
<name></name>
<script></script>
</card>
card_32462.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
For example, consider the alternate </span><span class="style4">square()</span><span class="style3"> function, with no return value:
</span><span class="style4">
void square(float *f_ptr)
{
*f_ptr = (*f_ptr) * (*f_ptr);
}
</span><span class="style3">This function may be called from another function as:
</span><span class="style4">
square(&the_value);
</span><span class="style3">The value contained in the variable </span><span class="style4">the_value</span><span class="style3"> is thus squared.
This technique is also used when passing an array to a function, since the array name is treated as a pointer to the zeroth element of the array. To pass this pointer as an argument, the array identifier is given without brackets. An example is the following function which squares each element of an array containing 3 elements.</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>100</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p142</text>
</content>
<name></name>
<script></script>
</card>
card_32640.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
</span><span class="style3">An equivalent definition which is more appropriate in this case takes advantage of the use of array indexing in place of pointer arithmetic:
</span><span class="style4">
void square_array(float f_array[])
{
f_array[0] = f_array[0] * f_array[0];
f_array[1] = f_array[1] * f_array[1];
f_array[2] = f_array[2] * f_array[2];
}</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>101</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p142</text>
</content>
<name></name>
<script></script>
</card>
card_32967.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">he declaration "</span><span class="style4">float f_array[]</span><span class="style3">" in the second version is a synonym for declaring </span><span class="style4">f_array</span><span class="style3"> to be a float pointer. The number of elements in the array is inconsequential since </span><span class="style4">f_array</span><span class="style3"> is treated as a pointer. The choice of notation is usually made based on how the pointer is to be used in the function.
The calling function may pass the array name to the new </span><span class="style4">square()</span><span class="style3"> function as follows:
</span><span class="style4">
float array_of_floats[3]; // declare array of 3 floats
array_of_floats[0] = 19.;
array_of_floats[1] = 92.;
array_of_floats[2] = 33.;
square_array(array_of_floats);
</span><span class="style3">In addition to allowing the called function to affect the values of variables in the calling function, pointers are frequently used as function arguments to avoid the inefficiency of passing large user-defined structure variables to the function. Rather, a pointer to the structure is passed.</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>102</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p142</text>
</content>
<name></name>
<script></script>
</card>
card_31005.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3"> programs are usually divided into several source files, to improve modularity and to speed program development. (Only the altered functions need to be recompiled.)
By default function identifiers have </span><span class="style7">file scope</span><span class="style3">, so the function can be accessed from any point following its declaration in a source file, and from any other source files which provide a suitable declaration.*
Recall that a function </span><span class="style7">definition</span><span class="style3"> describes the structure of the function whereas a </span><span class="style7">declaration</span><span class="style3"> simply informs the compiler of the types of the function's return value and arguments. A complete function definition involves both the function prototype (the header) and the function body. A function definition also serves as a function declaration. Therefore if the called function's definition precedes the calling function in the source file, then no further declaration is needed.
If, however, a function is called before it is defined in the source file, or if the function is called from a function in another source file, then a declaration must be given. A function is declared simply by giving the prototype followed by a </span></text>
</content>
<content>
<layer>background</layer>
<id>6</id>
<text>3.3 Scope</text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>103</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>20338</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>ANSI C scopes</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>ANSI C scopes - p84</text>
</content>
<name></name>
<script></script>
</card>
card_31508.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">emicolon. It is not necessary to list the names of the formal parameters; only their types. For example:
</span><span class="style4">
float square(float);
</span><span class="style3">It is common practice to place lists of function prototype declarations in header files.*
Note that pre-ANSI C code does not use complete function prototype declarations. Rather, a function is declared by stating the type of its return value and following the function identifier with empty parentheses to distinguish it as a function rather than a variable:
</span><span class="style4">
float square();
</span><span class="style3">The default return type for functions is </span><span class="style4">int</span><span class="style3">, and many pre-ANSI programs took advantage of this by not declaring those functions which returned ints at all.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>104</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>52189</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>File inclusion</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>File inclusion - p199</text>
</content>
<name></name>
<script></script>
</card>
card_32050.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">hile some ANSI C compilers permit these short cuts, it is considered good practice to provide full prototype declarations for all functions. In addition to aiding program maintenance, this allows the compiler to enforce type checking of the arguments, reducing type-conversion bugs.
The default file scope for function identifiers can be restricted with the </span><span class="style4">static</span><span class="style3"> specifier*, which disallows access from source files other from the one in which the function is defined.
Functions cannot have block scope, but TC and C++ functions can have class scope (Chapter 4). This limits the function's scope to that of the body of data with which it is associated, which itself may be block scope, and to the bodies of other functions of the same class.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>105</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>28872</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>Scope restriction with 'static'</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>Scope restriction with 'static' - p88</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p210</text>
</content>
<name></name>
<script></script>
</card>
card_9318.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">ll C programs begin execution with the function entitled </span><span class="style4">main</span><span class="style3">, and end execution when this function terminates. The arguments and return value of this function are assigned and evaluated in an operating system-dependent manner.
Unix systems allow command-line arguments to be provided when a program is executed. These arguments are usually assigned to </span><span class="style4">argv</span><span class="style3"> and </span><span class="style4">argc</span><span class="style3"> parameters which the </span><span class="style4">main()</span><span class="style3"> function may optionally access.
If the </span><span class="style4">main()</span><span class="style3"> function provides a </span><span class="style4">return</span><span class="style3"> statement, the value returned may be evaluated by the operating system to provide feedback to the user.
Think C for the Macintosh provides the </span><span class="style4">ccommand()</span><span class="style3"> function to simulate the use of command-line arguments. Generally, the </span><span class="style4">main()</span><span class="style3"> function in Macintosh programs uses neither arguments nor a return value.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>106</text>
</content>
<content>
<layer>background</layer>
<id>6</id>
<text>3.4 The main() Function</text>
</content>
<content>
<layer>background</layer>
<id>18</id>
<text>p251</text>
</content>
<name></name>
<script></script>
</card>
card_33872.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3"> functions may call themselves in a </span><span class="style7">recursive</span><span class="style3"> fashion. For example, a function to raise a floating-point number to an integral power may be written:
</span><span class="style4">
float expon(float x, int y)
{
if (y>0)
return x * expon(x,y-1);
else
return 1.;
}
</span><span class="style3">The scope of the formal parameters (and local variables, if any) of a function is the body of the function, and separate values for these variables are maintained for each invocation of the function. Thus there is no conflict when passing the value "</span><span class="style4">y-1</span><span class="style3">" as an argument to the </span><span class="style4">expon()</span><span class="style3"> function, even though the identifier </span><span class="style4">y</span><span class="style3"> is itself used as a parameter of the called function.</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>107</text>
</content>
<content>
<layer>background</layer>
<id>6</id>
<text>3.5 Recursion</text>
</content>
<name></name>
<script></script>
</card>
card_34369.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">n addition to containing the address of a variable, pointers may contain the address of a function. This is a rather confusing notion; nonetheless function pointers find uses in certain applications.
Function pointers are declared in a manner similar to a function prototype declaration. For example, a pointer to a function which returns a float and accepts one float and one int argument would be declared as follows:
</span><span class="style4">
float (*func_ptr)(float,int);
</span><span class="style3">(In pre-ANSI C, the types of the arguments would be omitted from this declaration.) The parentheses surrounding "</span><span class="style4">*func_ptr</span><span class="style3">" are required; otherwise this becomes a function prototype for a function returning a float pointer.
Since function identifiers may not themselves be passed as arguments to other functions, function pointers are often used for this purpose. The called function declares one of its formal parameters to be a function pointer. A function pointed to </span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>108</text>
</content>
<content>
<layer>background</layer>
<id>6</id>
<text>3.6 Function Pointers</text>
</content>
<name></name>
<script></script>
</card>
card_35573.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">y a function pointer is called by using the </span><span class="style4">*</span><span class="style3"> ("that which is pointed to by") operator with the function pointer, although ANSI C allows the </span><span class="style4">*</span><span class="style3"> to be omitted(!). The following function takes one function pointer and one float as arguments, and returns the result of applying the function pointed to by the function pointer twice.
</span><span class="style3">The calling function passes the address of the desired function as an argument to the called function. As with array identifiers, the function identifier itself represents its address — the </span><span class="style4">&</span><span class="style3"> operator is not needed. The calling function may pass the </span><span class="style4">square()</span><span class="style3"> function to </span><span class="style4">perform_twice()</span><span class="style3"> as an argument, in order to find the 4th power of a value:
<text><span class="style3">he C language has very few reserved words or built-in operators. Rather, it relies upon the existence of function </span><span class="style7">libraries</span><span class="style3"> to empower the programmer. The use of function libraries allows the C language to be customized for particular environments and application areas, contributing to its efficiency and flexibility.
ANSI C compilers include a standard function library which provides functions for mathematical operations, input/output, string handling, memory allocation, etc. (Pre-ANSI C compilers often used separate libraries for these collections of functions.) These functions may be accessed directly from any of the programmer's own functions, provided an appropriate declaration for the library function precedes its use in the source file.
The programmer should not declare the standard functions himself/herself. Rather, the appropriate standard header files should be referenced, as discussed further in Chapters 7 and 8. These header files themselves contain the declarations for the corresponding library functions. In this way, the program is less likely to be affected by future changes to the function libraries.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>110</text>
</content>
<content>
<layer>background</layer>
<id>6</id>
<text>3.7 Library Functions</text>
</content>
<name></name>
<script></script>
</card>
card_33418.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">or example, if the programmer uses the standard I/O function </span><span class="style4">printf()</span><span class="style3"> and the string copy function </span><span class="style4">strcpy()</span><span class="style3">, then the appropriate declarations for these functions are referenced by inserting the following instructions at the top of the source file:
</span><span class="style4">
# include <stdio.h>
# include <string.h>
</span><span class="style3">These preprocessor directives* cause the declarations contained in the header files </span><span class="style18">stdio.h</span><span class="style3"> and </span><span class="style18">string.h</span><span class="style3"> to be inserted into the programmer's source file. Chapter 8 describes several useful standard functions and their header files.
Most environments provide additional specialized libraries and header files, and allow programmers to define new ones. The compiler must be alerted which of these non-standard libraries is in use, so that it can locate the needed functions when linking the completed program.
Macintosh C compilers provide header files declaring the ROM "Toolbox" functions which enable the Macintosh interface, so they can be treated as a C function library.</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>111</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>52189</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>File inclusion</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>File inclusion - p199</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p223</text>
</content>
<name></name>
<script></script>
</card>
card_7960.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">he scrolling text fields on the following two pages contain code which may be pasted into the source files </span><span class="style18">functest.c</span><span class="style3"> and </span><span class="style18">contchar.c</span><span class="style3">, and compiled. This brief program demonstrates the use of recursion in string-handling functions and the use multiple source files.</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>112</text>
</content>
<content>
<layer>background</layer>
<id>18</id>
<text>p207</text>
</content>
<name></name>
<script></script>
</card>
card_30088.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">n </span><span class="style7">object</span><span class="style3"> is a variable which represents a collection of data (like a C </span><span class="style4">struct</span><span class="style3">*) and also represents the procedures which may act upon this data. Structuring programming efforts according to appropriate objects (rather than functions or procedures) is said to improve problem analysis, by more closely modelling the real-world problem of interest. This in turn aids program development, understandability, and maintenance. It is possible to define an object using traditional C syntax, by encapsulating the data and related procedures in a separate source file.
Think C and C++ extend traditional C by providing new syntax for consistent definition of objects, and by allowing the definition of </span><span class="style7">classes</span><span class="style3"> of objects. This promotes the object-oriented programming (OOP) approach, which in turn can lead to more concise and flexible (reusable) code.
This chapter describes the extensions provided by TC and C++, and discusses several programming considerations. C++ provides several additional details for OOP which are not supported by TC. These extensions will </span><span class="style7">not</span><span class="style3"> be detailed in this text, but are mentioned briefly where relevant and are summarized in Appendix 2.</span></text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>25150</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>User-defined data structures</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>User-defined data structures - p75</text>
</content>
<name></name>
<script></script>
</card>
card_36058.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">C/C++ supports OOP simply by extending the existing </span><span class="style4">struct</span><span class="style3"> user-defined type available in C. The definition of a user-defined struct type is said to be a </span><span class="style7">class</span><span class="style3"> definition if function prototype declarations are included as members of the struct. In this case, the members which are variable declarations are said to declare </span><span class="style7">instance variables</span><span class="style3"> and the "member function" declarations are said to declare the </span><span class="style7">methods</span><span class="style3"> which apply to these variables. The following defines the </span><span class="style4">Person</span><span class="style3"> class, which declares </span><span class="style4">age</span><span class="style3"> and </span><span class="style4">weight</span><span class="style3"> instance variables, and </span><span class="style4">set()</span><span class="style3"> and </span><span class="style4">print()</span><span class="style3"> methods:
</span><span class="style4">
struct Person:indirect // for C++ omit ':indirect'
{
int age;
int weight;
virtual void set(void);
virtual void print(void);
};
</span><span class="style3">(A useful convention is to begin all class names with a capital letter.)
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>116</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p210</text>
</content>
<name></name>
<script></script>
</card>
card_36204.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">he </span><span class="style4">indirect</span><span class="style3"> specifier indicates how TC implements objects of this class, and is discussed later.* It is not used in C++. The </span><span class="style4">virtual</span><span class="style3"> specifier identifies the </span><span class="style4">set()</span><span class="style3"> and </span><span class="style4">print()</span><span class="style3"> methods as "virtual" methods, whose significance will be seen later.**
The </span><span class="style4">set()</span><span class="style3"> and </span><span class="style4">print()</span><span class="style3"> methods are defined using the new </span><span class="style7">scope resolution</span><span class="style3"> operator, </span><span class="style4">::</span><span class="style3">. This associates the function definitions with the appropriate class. For example:
</span><span class="style4">
void Person::set(void)
{
age = 62;
weight = 155;
}
</span><span class="style3">The instance variables declared in the </span><span class="style4">Person</span><span class="style3"> class are accessible from within the body of the member function definitions without need for the dot or </span><span class="style4">-></span><span class="style3"> operators usually needed to access structure members. However, if a method definition uses a local variable with the same identifier as an instance variable, the instance variable can be accessed using the automatically-declared </span><span class="style4">this</span><span class="style3"> pointer, e.g.: </span><span class="style4">this->age = 62</span><span class="style3">.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>117</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>38494
43887</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>Macintosh memory management
Virtual methods</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>Macintosh memory management - p158</text>
</content>
<content>
<layer>background</layer>
<id>23</id>
<text>Virtual methods - p128</text>
</content>
<name></name>
<script></script>
</card>
card_36371.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
An important object-oriented technique is that of deriving new classes from existing classes. A derived class (descendant, child or subclass) is one which </span><span class="style7">inherits</span><span class="style3"> the instance variable and method declarations of the base class (ancestor, parent or superclass), and adds instance variables and methods of its own. A derived class may also provide new definitions for the methods declared in the base class, in which case the new definition is said to "override" the original. (If the original method was "virtual", then there is no need to use the </span><span class="style4">virtual</span><span class="style3"> keyword when overriding the method.) The syntax to derive the </span><span class="style4">Student</span><span class="style3"> class from the </span><span class="style4">Person</span><span class="style3"> class is:
</span><span class="style4">
struct Student:Person
{
int student_num; // additional instance variable
void set(void); // override original set() method
void print(void); // override original print() method
};</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>118</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p202</text>
</content>
<name></name>
<script></script>
</card>
card_36702.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">ince it is derived from the </span><span class="style4">Person</span><span class="style3"> class, the </span><span class="style4">Student</span><span class="style3"> class implicitly declares </span><span class="style4">age</span><span class="style3"> and </span><span class="style4">weight</span><span class="style3"> instance variables as well. It is necessary to redefine any methods which were redeclared in the new class definition, for example:
</span><span class="style4">
void Student::set(void)
{
student_num = 12345;
Person::set();
}
</span><span class="style3">The </span><span class="style4">Person::set()</span><span class="style3"> syntax invokes the </span><span class="style4">set()</span><span class="style3"> method of the base class*, which itself assigns values to the inherited </span><span class="style4">age</span><span class="style3"> and </span><span class="style4">weight</span><span class="style3"> instance variables. In Think C an alternative syntax (not available in C++) may be used: </span><span class="style4"> inherited::set()</span><span class="style3">.
It is possible to derive additional classes from the </span><span class="style4">Student</span><span class="style3"> class to obtain still more-specialized classes. In fact, it is customary to derive </span><span class="style7">all</span><span class="style3"> classes in an application from a single class and its descendants, creating a hierarchy or "tree". For the remainder of this chapter we will use the class </span><span class="style4">Generic_Class</span><span class="style3"> as this "root" class:
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>119</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>38674</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>Invoking methods from within other methods</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>Invoking methods from within other methods - p125</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p189</text>
</content>
<name></name>
<script></script>
</card>
card_37092.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
struct Generic_Class:indirect // for C++ omit ':indirect'
{
boolean initialized;
virtual boolean is_initialized(void);
};
boolean Generic_Class::is_initialized(void)
{
return initialized;
}
</span><span class="style3">The </span><span class="style4">is_initialized()</span><span class="style3"> method will thus be inherited by all classes. Its use will be discussed later.* (The </span><span class="style4">boolean</span><span class="style3"> data type represents "true" and "false" values only, and is defined a synonym for </span><span class="style4">int</span><span class="style3"> using </span><span class="style4">typedef</span><span class="style3">.</span><span class="style4">**</span><span class="style3">)
Let's redefine the </span><span class="style4">Person</span><span class="style3"> class to be derived from the </span><span class="style4">Generic_Class</span><span class="style3">:
</span><span class="style4">
</span><span class="style3">
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>120</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>Constructors
Using typedef
</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>43696
26498
</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>Constructors - p133</text>
</content>
<content>
<layer>background</layer>
<id>23</id>
<text>Using typedef - p79</text>
</content>
<name></name>
<script></script>
</card>
card_37863.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
</span><span class="style3">Now both the </span><span class="style4">Person</span><span class="style3"> and </span><span class="style4">Student</span><span class="style3"> classes inherit the </span><span class="style4">is_initialized()</span><span class="style3"> method.
To clarify program structure, ease code reusability, and speed up development (via separate compilation), it is customary to place the definition of each class in a separate header file* and to place the definitions for a given class' methods in a separate source file. This will be demonstrated in the example later in this chapter.</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>121</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>52189</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>File inclusion</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>File inclusion - p199</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p189</text>
</content>
<name></name>
<script></script>
</card>
card_37143.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">hus far we have not declared any variables whose type is a class. Such variables are called </span><span class="style7">objects</span><span class="style3">. In TC (but not in C++) it is illegal to declare an identifier which is itself an object. Rather, we must declare an identifier which is a pointer to an object of the desired class. This pointer will be called the </span><span class="style7">object reference</span><span class="style3">. Generally, we will not bother to indicate in its name that it is a pointer (e.g. </span><span class="style4">float *f_ptr</span><span class="style3">). In fact, we will often speak of the object reference as though it were the object itself.
</span><span class="style4">
Student *jack; // note: 'struct Student' is not needed
</span><span class="style3">Recall that defining a pointer to a data type allocates space only for a machine address; it does not allocate space for a variable of this type — in this case a </span><span class="style4">Student</span><span class="style3"> object — itself. The </span><span class="style4">new</span><span class="style3"> operator allocates space for the instance variables of an object of the specified class and returns a pointer to this space.
</span><span class="style4">
jack = new Student;
</span><span class="style3">Unlike the case with variables having "automatic" storage class*, space allocated by the </span><span class="style4">new</span><span class="style3"> operator is not deallocated upon completion of the function in which it is
</span></text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>28174</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>Automatic storage</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>Automatic storage - p86</text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>122</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p189</text>
</content>
<name></name>
<script></script>
</card>
card_37607.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">llocated. Rather, such "free-store" variables must be deallocated explicitly by the programmer as discussed below. (Notice that the object reference will often have automatic storage. This means that if the function terminates before the object is explicitly deallocated, then the object reference will be deallocated and the program may no longer be able to access or reclaim the space occupied by the object.)
Since </span><span class="style4">jack</span><span class="style3"> is a pointer, the </span><span class="style4">-></span><span class="style3"> operator may be used to access the members of the object to which </span><span class="style4">jack</span><span class="style3"> points, in the same way as for traditional C structures.
</span><span class="style4">
jack->age = 19;
</span><span class="style3">The scope of the instance variables is the same as the scope of the object reference, except that (as mentioned in the previous section) the instance variables may also be accessed from within the definitions of methods for this class, without need for the </span><span class="style4">-></span><span class="style3"> operator. The instance variables are said to have </span><span class="style7">class scope</span><span class="style3">.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>123</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p189</text>
</content>
<name></name>
<script></script>
</card>
card_38203.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
In fact, it is considered bad practice to access the instance variables of an object outside of the method definitions. Rather, all communication with the object should generally be accomplished by calling its methods, or — in OOP terminology — sending it </span><span class="style7">messages</span><span class="style3">:
</span><span class="style4">
jack->set();
jack->print();
</span><span class="style3">By restricting access in this way, the implementation of the instance variables may later be changed, along with the appropriate methods, without affecting the functions which declare and use objects of this class. As will be seen later in this chapter, access specifiers may be used to enforce this restriction.
Notice that in order to send a </span><span class="style4">print</span><span class="style3"> message you must refer to the identifier </span><span class="style4">jack</span><span class="style3">, which is a pointer to an object of this class. In effect the scope of the </span><span class="style4">print()</span><span class="style3"> method
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>124</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p189</text>
</content>
<name></name>
<script></script>
</card>
card_38674.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">s restricted to the scope of the object reference. As is the case with variables having class scope, </span><span class="style4">print()</span><span class="style3"> may also be invoked from within another method which belongs to the same class. In this case the object reference may be omitted as it is when referring to instance variables from within the method.
For example, we may wish to immediately print the values of instance variables set in the </span><span class="style4">Student::set()</span><span class="style3"> method, by sending a </span><span class="style4">print</span><span class="style3"> message:
</span><span class="style4">
void Student::set(void)
{
student_num = 12345;
Person::set();
print();
}
</span><span class="style3">This is equivalent to:
</span><span class="style4">
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>125</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>36702</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>Previous definition of Student::set()</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>Previous definition of Student::set() - p119</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p189</text>
</content>
<name></name>
<script></script>
</card>
card_38944.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
</span><span class="style3">where the </span><span class="style4">this</span><span class="style3"> identifier is an automatically-declared object reference to the "object which received the message."
As mentioned in the previous section, </span><span class="style4">Person::set()</span><span class="style3"> invokes the </span><span class="style4">set()</span><span class="style3"> method defined for the </span><span class="style4">Person</span><span class="style3"> class, which is an ancestor of the </span><span class="style4">Student</span><span class="style3"> class. The methods of ancestral classes may be accessed through an object reference (including the </span><span class="style4">this</span><span class="style3"> object reference), provided they were not given the </span><span class="style4">private</span><span class="style3"> access specifier to be discussed later in this chapter.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>126</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p189</text>
</content>
<name></name>
<script></script>
</card>
card_64952.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
The space pointed to by an object reference must be deallocated by the programmer once the object is no longer needed. This is done with the converse of the </span><span class="style4">new</span><span class="style3"> operator: the </span><span class="style4">delete</span><span class="style3"> operator. It simply deallocates the object pointed to by its operand.
</span><span class="style4">
delete jack;
</span><span class="style3">The object reference </span><span class="style4">jack</span><span class="style3"> is not itself deallocated; only the space to which it points. At this point, sending a message to </span><span class="style4">jack</span><span class="style3"> is likely to cause the program to crash:
</span><span class="style4">
jack->set(); // will probably cause a crash if jack has been deleted!
</span><span class="style3">If </span><span class="style4">jack</span><span class="style3"> was never allocated (using the </span><span class="style4">new</span><span class="style3"> operator) at all, then it is also possible to crash the program simply by applying the </span><span class="style4">delete</span><span class="style3"> operator to </span><span class="style4">jack</span><span class="style3">. This problem can be avoided by initializing the object reference </span><span class="style4">jack</span><span class="style3"> to the </span><span class="style4">NULL</span><span class="style3"> pointer.* Applying the </span><span class="style4">delete</span><span class="style3"> operator to </span><span class="style4">NULL</span><span class="style3"> has no effect.
</span></text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>69591</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>NULL pointer</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>NULL pointer - p67</text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>127</text>
</content>
<name></name>
<script></script>
</card>
card_43887.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">t is legal in TC/C++ to assign a pointer for an object of one class to a pointer for a </span><span class="style7">base</span><span class="style3"> class. For example, if the </span><span class="style4">Student</span><span class="style3"> class is a descendant of the </span><span class="style4">Person</span><span class="style3"> class, you may declare an object reference which is a </span><span class="style4">Person</span><span class="style3"> pointer, and assign a </span><span class="style4">Student</span><span class="style3"> pointer to this object reference.
C is a </span><span class="style7">strongly-typed</span><span class="style3"> language. The compiler makes use of the known (at compile-time) type of a value to generate code which will handle it correctly. Therefore, it is the compile-time type of the object reference which is important, not the run-time type of the pointer assigned to this reference. For example, suppose the </span><span class="style4">Student</span><span class="style3"> class has a new instance variable </span><span class="style4">id_number</span><span class="style3">:
</span><span class="style4">
Person *person;
person = new Student;
person->age = 18; //ok so far
person->id_number = 123; // compilation error: "no such member"
</span><span class="style3">A compilation error occurs in the fourth line because the compiler still thinks </span><span class="style4">person</span><span class="style3"> is a reference to a </span><span class="style4">Person</span><span class="style3"> object, which wouldn't have an </span><span class="style4">id_number</span><span class="style3"> member. (The
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>128</text>
</content>
<content>
<layer>background</layer>
<id>6</id>
<text>4.3 Virtual Methods and Typing</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p66</text>
</content>
<name></name>
<script></script>
</card>
card_67716.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">roblem vanishes when the first line is: "</span><span class="style4">Student *person</span><span class="style3">", or when a cast* is used.)
</span><span class="style4">
</span><span class="style3">However, TC/C++ contains a mechanism to determine the type of an object at run-time, for the sole purpose of invoking the correct method when a message is sent to this object. This mechanism is used only for </span><span class="style7">virtual methods</span><span class="style3">. A virtual method is one which was declared with the </span><span class="style4">virtual</span><span class="style3"> specifier, or one which descends from a virtual method. For example:
</span><span class="style4">
struct A:Generic_Class
{
void m1(void);
virtual void m2(void);
virtual void m3(void);
};
struct B:A
{
void m1(void);
virtual void m2(void); // 'virtual' here is optional, but good style
};
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>129</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p66</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>69198</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>Casts for identifying objects</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>Casts for identifying objects - p131</text>
</content>
<name></name>
<script></script>
</card>
card_68019.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">We assume the bodies of the </span><span class="style4">A::m1()</span><span class="style3">, </span><span class="style4">A::m2()</span><span class="style3">, </span><span class="style4">A::m3()</span><span class="style3">, </span><span class="style4">B::m1()</span><span class="style3">, and </span><span class="style4">B::m2()</span><span class="style3"> methods are defined elsewhere.) Now we declare a reference to an </span><span class="style4">A</span><span class="style3"> object, and assign it a newly-allocated </span><span class="style4">B</span><span class="style3"> object:
</span><span class="style4">
A *a;
a = new B;
a->m1();
a->m2();
a->m3();
</span><span class="style3">The first method carried out is </span><span class="style4">A::m1()</span><span class="style3">, since the compile-time type of the object reference </span><span class="style4">a</span><span class="style3"> is </span><span class="style4">A</span><span class="style3">. However, the second method carried out is </span><span class="style4">B::m2()</span><span class="style3">, since </span><span class="style4">m2</span><span class="style3"> is a virtual method and the run-time type of the object pointed to by </span><span class="style4">a</span><span class="style3"> is </span><span class="style4">B</span><span class="style3">. The third method carried out is </span><span class="style4">A::m3()</span><span class="style3"> since it is simply inherited by the </span><span class="style4">B</span><span class="style3"> class.
</span><span class="style4">
</span><span class="style3">It is common to declare almost all methods as virtual, to encourage </span><span class="style7">polymorphism</span><span class="style3">: the property whereby the same message may be sent to various objects with the results appropriate to each. In fact, Think C provides a "Methods are virtual by default" compilation option.</span><span class="style4">
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>130</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p66</text>
</content>
<name></name>
<script></script>
</card>
card_69198.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
It is frequently useful to declare an array of pointers to a base class, each of which is assigned a newly-allocated object of a derived class. For example:
</span><span class="style4">
Person *person[10];
person[0] = new Person;
person[1] = new Student;
person[2] = new Grad_Student;
.
.
</span><span class="style3">If virtual methods are used, then </span><span class="style4">set</span><span class="style3"> and </span><span class="style4">print</span><span class="style3"> messages can be sent to any element of the array to invoke the </span><span class="style4">set()</span><span class="style3"> and </span><span class="style4">print()</span><span class="style3"> methods belonging to the run-time class of the object. However, if a derived class declares a new method not contained in the base class, then the compiler must be informed of the class of the object before it will accept this message.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>131</text>
</content>
<name></name>
<script></script>
</card>
card_44045.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">or example, suppose the </span><span class="style4">Student</span><span class="style3"> class defines a new method called </span><span class="style4">set_roommate()</span><span class="style3">. Then a compilation error (similar to that discussed at the beginning of this section) will occur when the following line is encountered:
</span><span class="style4">
person[1]->set_roommate(); // compilation error: "no such member"
</span><span class="style3">Since all elements of the array are declared at compile-time to be </span><span class="style4">Person</span><span class="style3"> pointers, a </span><span class="style7">cast</span><span class="style3">* must be used to inform the compiler of the correct type for </span><span class="style4">person[1]</span><span class="style3">:
</span><span class="style4">
((Student*) person[1])->set_roommate();
</span><span class="style3">
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>132</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>47191</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>Casts for type conversion</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>Casts for type conversion - p175</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p66</text>
</content>
<name></name>
<script></script>
</card>
card_43696.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">t is customary to initialize objects immediately after allocation, and "clean up" after them before deallocating. TC/C++ provide a facility for "constructing" and "destroying" objects automatically upon allocation and deallocation. Since this convenience feature was added to Think C only recently, many Think C programs instead use separate </span><span class="style4">init()</span><span class="style3"> and </span><span class="style4">dispose()</span><span class="style3"> methods to handle this. C++ still provides greater flexibility than does Think C; therefore, this section describes only those techniques which work equally under Think C and C++.
A </span><span class="style7">constructor</span><span class="style3"> is a method whose name is the name of the class. This method is invoked automatically upon allocation of an object of this class; e.g. when the </span><span class="style4">new</span><span class="style3"> operator is applied. Its purpose is to initialize and/or allocate the instance variables of the object. A </span><span class="style7">destructor</span><span class="style3"> is a method whose name is the name of the class, preceded by the ~ ("tilde") symbol. Its purpose is to deallocate any instance variables which have the "free store" storage class (including those instance variables which are themselves objects). The destructor is invoked automatically when an object is deallocated; e.g. when the </span><span class="style4">delete</span><span class="style3"> operator is applied.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>133</text>
</content>
<content>
<layer>background</layer>
<id>6</id>
<text>4.4 Constructors & Destructors</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p46</text>
</content>
<name></name>
<script></script>
</card>
card_70218.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">onstructors and destructors may not declare any return value, and may only declare the void parameter. (Constructors may take arguments in C++ but not in Think C.) They are always virtual in Think C: the run-time type of the object determines which constructor or destructor is invoked. (Since C++ destructors may be virtual or non-virtual, you should declare Think C destructors virtual for compatibility.)
If a class is not a root class (that is, it has a parent class), then the constructors and destructors of </span><span class="style7">all</span><span class="style3"> its ancestors are called, in sequence, when an object of the class is allocated and deallocated. (The sequence is root-to-class for constructors and class-to-root for destructors.) Therefore, it is good practice to use a constructor to initialize only those instance variables which are newly declared in a given class. The instance variables which are inherited from the parent class should be initialized in the parent class' constructor. Likewise, the destructor should only deallocate those instance variables which were initialized by the constructor of the same class.
In the following example, class </span><span class="style4">A</span><span class="style3"> is a root class and class </span><span class="style4">B</span><span class="style3"> descends from </span><span class="style4">A</span><span class="style3">:
</span></text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p46</text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>134</text>
</content>
<content>
<layer>background</layer>
<id>18</id>
<text>p130</text>
</content>
<name></name>
<script></script>
</card>
card_70687.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">he instance variable </span><span class="style4">c1</span><span class="style3"> is an object reference to an object of class </span><span class="style4">C</span><span class="style3"> (which should be defined elsewhere). </span><span class="style4">c1</span><span class="style3"> is inherited by objects of class </span><span class="style4">B</span><span class="style3">. However, </span><span class="style4">c1</span><span class="style3"> is not initialized in the constructor for class </span><span class="style4">B</span><span class="style3">. Instead, it is initialized in the constructor for class </span><span class="style4">A</span><span class="style3"> where it was first declared.
</span><span class="style4">
B *b;
b = new B; // allocate b and invoke constructors
...
delete b; // deallocate b and invoke destructors
</span><span class="style3">When an object </span><span class="style4">b</span><span class="style3"> class </span><span class="style4">B</span><span class="style3"> is allocated, the constructor for class </span><span class="style4">A</span><span class="style3"> is automatically invoked (allocating </span><span class="style4">c1</span><span class="style3">), followed by the constructor for class </span><span class="style4">B</span><span class="style3"> (allocating </span><span class="style4">c2</span><span class="style3">). Thus, all instance variables — inherited or otherwise — of </span><span class="style4">b</span><span class="style3"> are initialized once and only once.
Likewise, when </span><span class="style4">b</span><span class="style3"> is deallocated, the destructor for class </span><span class="style4">B</span><span class="style3"> is automatically invoked (deallocating </span><span class="style4">c2</span><span class="style3">) followed by the destructor for class </span><span class="style4">A</span><span class="style3"> (deallocating </span><span class="style4">c1</span><span class="style3">).</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>136</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p153</text>
</content>
<name></name>
<script></script>
</card>
card_71809.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
The </span><span class="style4">new</span><span class="style3"> operator usually returns a pointer to a newly-created object. However, if there is insufficient memory available to allocate this object, then the </span><span class="style4">NULL</span><span class="style3"> pointer* is returned instead. It is good practice to check whether this has occurred, especially when allocating large objects, since sending messages to </span><span class="style4">NULL</span><span class="style3"> can cause your program to crash.
It is also desirable to check whether your object failed to initialized successfully — for example when there is insufficient memory to allocate one of the instance variables.
One solution is to use a root class containing an "</span><span class="style4">initialized</span><span class="style3">" instance variable whose status indicates whether initialization was successful. Since the constructors of </span><span class="style7">all</span><span class="style3"> ancestors of a non-root class are called in sequence, they may each check the status of this instance variable to see whether the constructor of the parent class succeeded. The example later in this chapter illustrates this technique.</span></text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>69591</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>The NULL pointer</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>The NULL pointer - p67</text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>137</text>
</content>
<name></name>
<script></script>
</card>
card_68970.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3"> further OOP convenience (some say necessity) </span><span class="style3">provided by TC/C++ is the use of the </span><span class="style4">private</span><span class="style3">, </span><span class="style4">protected</span><span class="style3">, and </span><span class="style4">public</span><span class="style3"> </span><span class="style7">access specifiers</span><span class="style3">. The </span><span class="style4">public</span><span class="style3"> specifier is default for classes declared with </span><span class="style4">struct</span><span class="style3">. The </span><span class="style4">protected</span><span class="style3"> specifier restricts the scope of the instance variables and methods following it so they are accessible only within methods of the class or of derived classes. The </span><span class="style4">private</span><span class="style3"> specifier allows access to class members only within methods of the same class.
</span><span class="style4">
struct Rolls:Automobile
{
private:
char *favorite_wine[100];
int lookup_wine_list(char*);
public:
virtual void restock_wines(int);
};
</span><span class="style3">In this example, it is possible to access the </span><span class="style4">favorite_wine</span><span class="style3"> instance variable from within the body of the </span><span class="style4">restock_wines()</span><span class="style3"> method. However, the compiler will </span></text>
</content>
<content>
<layer>background</layer>
<id>6</id>
<text>4.5 Access Specifiers</text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>138</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p202</text>
</content>
<name></name>
<script></script>
</card>
card_68540.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">isallow access to </span><span class="style4">favorite_wine</span><span class="style3"> from other functions or methods. Likewise, you can only send </span><span class="style4">lookup_wine_list</span><span class="style3"> messages from within the body of the </span><span class="style4">restock_wines()</span><span class="style3"> method. Since</span><span class="style4"> restock_wines()</span><span class="style3"> is a public method, you can send </span><span class="style4">restock_wines</span><span class="style3"> messages from any methods or functions which have a </span><span class="style4">Rolls</span><span class="style3"> object in scope.
The constructors and destructors (previous section) of a class are usually declared public. Otherwise the compiler disallows allocating or deallocating objects of this class.
The purpose of access specifiers is to improve modularity in the class hierarchy. Typically all instance variables are made private to guard against direct access from outside the class. A few public methods remain to provide a well-defined interface to the class. This allows the programmer to change the implementations of the instance variables — and the methods which use them — without changing classes which derive from this class or which make use of objects of this class. C++ (but not Think C) also provides the ability to declare some classes as </span><span class="style4">friends</span><span class="style3"> with members of another class, to circumvent the usual privacy.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>139</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p153</text>
</content>
<name></name>
<script></script>
</card>
card_68283.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text>A limitation of TC/C++ access specifiers is that objects of a given class can always access private parts of other objects of the same class. Bjarne Stroustrup says, "The unit of protection in C++ is a class, not an individual object of a class", p. 138 of his seminal book.*</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>2231</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>Bibliography</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>Bibliography - p259</text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>140</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p153</text>
</content>
<name></name>
<script></script>
</card>
card_40401.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
By default, the public and protected members of a class declared with </span><span class="style4">struct</span><span class="style3"> remain public and protected in derived classes. However, you can preface the superclass name with </span><span class="style4">public</span><span class="style3"> or </span><span class="style4">private</span><span class="style3"> when declaring a new class, to change this inheritance property. In the example below, the public and protected members of class </span><span class="style4">A</span><span class="style3"> remain public and protected members of class </span><span class="style4">B</span><span class="style3">, but all members of class </span><span class="style4">A</span><span class="style3"> are private members of class </span><span class="style4">C</span><span class="style3">.
</span><span class="style4">
struct B:public A
{ ...
}
struct C:private A
{ ...
}
</span></text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p202</text>
</content>
<name></name>
<script></script>
</card>
card_43452.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
In addition to the extensions of the C </span><span class="style4">struct</span><span class="style3"> type, TC/C++ allows user-defined types to be declared using the </span><span class="style4">class</span><span class="style3"> keyword. Classes are defined with </span><span class="style4">class</span><span class="style3"> using the same syntax as classes defined with </span><span class="style4">struct</span><span class="style3">, except that the default access specifier is </span><span class="style4">private</span><span class="style3"> instead of </span><span class="style4">public</span><span class="style3">. Also, when a class is declared with </span><span class="style4">class</span><span class="style3"> and the superclass access is not specified, the default is </span><span class="style4">private</span><span class="style3"> instead of </span><span class="style4">public</span><span class="style3">. In this example, all inherited members of class </span><span class="style4">Person</span><span class="style3"> are private members of </span><span class="style4">Student</span><span class="style3">:
</span><span class="style4">
class Student:Person
{
...
};
</span><span class="style3">The (Think C only) "</span><span class="style4">:direct</span><span class="style3">" or "</span><span class="style4">:indirect</span><span class="style3">" specifiers* may be omitted from the declaration of a root class which is declared using the </span><span class="style4">class</span><span class="style3"> keyword. A compiler option allows selection between these specifiers. This simplifies porting code to C++ compilers.
</span><span class="style4">
</span><span class="style3">
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>142</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>Macintosh memory management
</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>38494</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>Macintosh memory management - p158</text>
</content>
<content>
<layer>background</layer>
<id>18</id>
<text>p251</text>
</content>
<name></name>
<script></script>
</card>
card_42427.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">he following pages contain source code for a complete example demonstrating the use of TC/C++ object-oriented programming techniques. Each page contains a scrol- ling text field whose contents may be pasted into an individual file for compilation.
As mentioned earlier, it is traditional to place the declaration for each class in a separate header file (indicated by the extension "</span><span class="style18">.h</span><span class="style3">" in the file name). The method definitions for each class are usually contained in a source file (indicated by the "</span><span class="style18">.c</span><span class="style3">" extension). The declarations in the headers may be accessed from the appropriate source files using the </span><span class="style4">#include</span><span class="style3"> preprocessor directive.* (Chapter 7 also discusses the </span><span class="style4">#define</span><span class="style3"> and </span><span class="style4">#ifndef</span><span class="style3"> directives used to prevent multiple references to the same header file, as well as an alternative approach available in Think C only.) Finally, the </span><span class="style18">main.c</span><span class="style3"> source file contains the </span><span class="style4">main()</span><span class="style3"> function where execution of the program begins.
The example is based on the "Person/Student" example described earlier, but makes use of access specifiers and constructors/destructors. A "class hierarchy" showing how each class is derived is illustrated below. This diagram is similar to that</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>143</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>52189</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>File inclusion</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>File inclusion - p199</text>
</content>
<name></name>
<script></script>
</card>
card_72172.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">resented by Think C's "Browser" feature, and is a useful documentation tool. In this sort of diagram it is important to note that the main relationship presented is that of inheritance, not containment. For example, although the </span><span class="style4">Checkbook</span><span class="style3"> class is not </span><span class="style7">derived</span><span class="style3"> from the </span><span class="style4">Person</span><span class="style3"> class (a </span><span class="style4">Checkbook</span><span class="style3"> is not a "kind of" </span><span class="style4">Person</span><span class="style3">), the </span><span class="style4">Person</span><span class="style3"> class may </span><span class="style7">contain</span><span class="style3"> an instance variable of class </span><span class="style4">Checkbook</span><span class="style3">.
<text>There are a few additional C++ features which have recently been added to Think C, though their use is not mandatory for writing good object-oriented programs. These are discussed very briefly in this section, and the reader is referred to the Think C manuals or to another C++ reference* for more details.
If you are writing programs in a C++ environment, you may also wish to investigate the many additional features not available in Think C. Again, these features are not mandatory for using C++, but may prove useful in large projects. Appendix 2 lists these features.</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>2231</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>Bibliography</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>Bibliography - p259</text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>154</text>
</content>
<name></name>
<script></script>
</card>
card_69749.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
A </span><span class="style7">class variable</span><span class="style3"> is a variable declared in a class definition, using the </span><span class="style4">static</span><span class="style3"> specifier. Only one "instance" of this variable exists, shared by all objects of this class. Thus class variables are useful for maintaining values through which common objects may communicate, in a "bulletin board" fashion. Since a class variable is not allocated when objects are allocated, it must be allocated separately as shown below.
Similarly, a </span><span class="style7">class method</span><span class="style3"> is a method declared using the </span><span class="style4">static</span><span class="style3"> specifier. Since this method is not associated with any given object of the class, you cannot access the (non-static) instance variables of the class without explicitly providing an object reference. Class methods usually serve as "utilities" for a given class. Note that in Think C it is possible to take the address of a class method but not of other methods.
You must use the</span><span class="style4"> :: </span><span class="style3">scope resolution operator to identify the class of a class variable or a class method, though it may be omitted within the body of a class method of the same class. For example*:
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>155</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>46228</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>Conditional (a?b:c) operator</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>Conditional (a?b:c) operator - p171</text>
</content>
<name></name>
<script></script>
</card>
card_73152.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
C++ allows you to "overload" an operator, so that its effect depends on the type you apply it to. (This is similar to the polymorphism provided by virtual methods.) In particular, it is occasionally useful to overload the </span><span class="style4">new</span><span class="style3"> and </span><span class="style4">delete</span><span class="style3"> operators to customize how a particular class is allocated and deallocated. This is the </span><span class="style7">only</span><span class="style3"> case where operator overloading is supported in Think C. The syntax is:
</span><span class="style4">
class Student:Person
{
void* operator new(size_t); // size_t is declared in <stddef.h>
...
};
void* Student::operator new(size_t num_bytes)
{
...
}</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>157</text>
</content>
<name></name>
<script></script>
</card>
card_38494.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">his section does not apply to C++. Most Think C classes are defined using the </span><span class="style4">indirect</span><span class="style3"> specifier, or are descended from a class using this specifier. When a pointer to an object of this type is declared, the pointer is actually implemented as a </span><span class="style7">handle</span><span class="style3">. Macintosh handles are pointers to pointers. Using handles to refer to data allows the Macintosh memory management routines to dynamically restructure memory ("move memory") during program execution without disturbing the program. Since the TC compiler is aware what identifiers refer to objects, it allows the programmer to treat the identifiers as simple pointers without concern for the actual implementation as handles. There are a few situations, however, where awareness of this implementation is crucial.
Most significant is the rule: </span><span class="style7">never rely upon the address of an instance variable during calls to functions which invoke memory management routines</span><span class="style3">. The actual address may change during memory management due to the handle implementation, causing "inexplicable" program crashes. Unfortunately many of TC's functions in the standard C libraries invoke memory management. For example, in the </span><span class="style4">Person::set()</span><span class="style3"> method we may wish to read a value from the user</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>158</text>
</content>
<name></name>
<script></script>
</card>
card_39343.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">with the </span><span class="style4">scanf()</span><span class="style3"> library function, into the </span><span class="style4">salary</span><span class="style3"> instance variable:
</span><span class="style4">
void Person::set(void)
{
printf("Enter salary:\n");
scanf("%g",&salary); // may bomb in TC with 'indirect' object
}
scanf()</span><span class="style3"> accepts the address of a variable as an argument, reads a value from the keyboard, and assigns the value to the variable pointed to by the address. If memory is moved, this action may overwrite important data used for another purpose. To avoid this problem, TC recommends a "shadowing" technique using local variables:
</span><span class="style4">
void Person::set(void)
{
float temp_salary;
printf("Enter salary:\n");
scanf("%g",&temp_salary); // bomb-free approach
salary = temp_salary;
}
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>159</text>
</content>
<content>
<layer>background</layer>
<id>18</id>
<text>p251</text>
</content>
<name></name>
<script></script>
</card>
card_39675.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">uppose a new instance variable is declared for the </span><span class="style4">Person</span><span class="style3"> class: a character array of length 80 called </span><span class="style4">name</span><span class="style3">. Remember that array names are considered in C to represent the address of the first element of the array. Therefore the following use of the standard string copy function may also cause program bombs:
</span><span class="style4">
void Person::set(void)
{
strcpy(name,"Jack Knapp"); // may cause bombs in TC
}
</span><span class="style3">Instead, the programmer must assign each character one by one (or write a string-copy function which doesn't move memory):
</span><span class="style4">
name[0] = 'J';
name[1] = 'a';
.
.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>160</text>
</content>
<content>
<layer>background</layer>
<id>18</id>
<text>p251</text>
</content>
<name></name>
<script></script>
</card>
card_39760.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">nother alternative in this case is to declare name to be a character pointer variable rather than an array. Then it may be assigned the address of a constant array direct- ly:
</span><span class="style4">
void Person::set(void)
{
name = "Jack Knapp"; // no problem with TC.
}
</span><span class="style3"> — or immobile space allocated dynamically with the standard </span><span class="style4">malloc()</span><span class="style3"> function*:</span><span class="style4">
void Person::set(void)
{
name = malloc((sizeof char) * 80); // dynamic allocation
strcpy(name,"Jack Knapp"); // ok if name is allocated with malloc()
}
</span><span class="style3">Occasionally these techniques will be inconvenient or inappropriate, and the Macintosh Toolbox routines </span><span class="style4">HLock()</span><span class="style3"> and </span><span class="style4">HUnlock()</span><span class="style3"> can be used to prevent indirect objects from moving. See the Think C manuals for further details.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>161</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>Dynamic memory allocation
</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>Dynamic memory allocation - p219</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>35106
</text>
</content>
<content>
<layer>background</layer>
<id>18</id>
<text>p251</text>
</content>
<name></name>
<script></script>
</card>
card_21830.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">nother interesting problem arose in Think C 4.0, when dealing with an instance variable which was itself an array of objects. Bombs could occur when a non-constant value was used to index the array for allocation, such as when the elements were allocated in a loop:
</span><span class="style4">
int Room::initialize(void)
{
int i;
for (i=0 ; i<MAX_STUDENTS ; i++)
{
student_array[i] = new(Student); // may bomb in Think C 4.0
}
}
</span><span class="style3">
The problem occurred because the left-hand side of the assignment expression was evaluated first, determining the location of the ith element of the array of object references. If the right-hand expression moved memory this address became incorrect. </span><span class="style7">This problem was "fixed" in Think C 5.0 by evaluating the right-hand side of the expression first.</span><span class="style3">
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>162</text>
</content>
<content>
<layer>background</layer>
<id>18</id>
<text>p251</text>
</content>
<name></name>
<script></script>
</card>
card_40041.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
To avoid the aforementioned problems, classes may be defined using the </span><span class="style4">direct</span><span class="style3"> specifier. In this case the implementation of object references is </span><span class="style7">not</span><span class="style3"> a handle, but is simply a pointer. However, this does not affect usage of the references.
</span><span class="style4">
class Person:direct
{
...
};
</span><span class="style3">This approach is useful when porting C++ programs to Think C. Using direct classes is also occasionally preferable to avoid overloading the Macintosh memory manager with many small objects.
</span><span class="style4">
</span><span class="style3">The drawback, as mentioned earlier, is that the Macintosh memory management routines have less freedom in dynamically restructuring memory since objects may not be moved.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>163</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>35106</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>Memory management functions</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>Memory management functions - p219</text>
</content>
<content>
<layer>background</layer>
<id>18</id>
<text>p251</text>
</content>
<name></name>
<script></script>
</card>
card_9080.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">everal miscellaneous C </span><span class="style7">operators</span><span class="style3"> have been introduced in previous chapters. The array subscripting operator</span><span class="style4"> []</span><span class="style3">, structure field selection operators</span><span class="style4"> . </span><span class="style3">and</span><span class="style4"> -></span><span class="style3">, "address of" and "that which is pointed to by" (indirection) operators</span><span class="style4"> & </span><span class="style3">and</span><span class="style4"> *</span><span class="style3">, and assignment operator</span><span class="style4"> = </span><span class="style3">were discussed in Chapter 2. The function call operator</span><span class="style4"> ()</span><span class="style3"> was given in Chapter 3. The comma operator</span><span class="style4"> , </span><span class="style3">is discussed in Chapter 6 and the </span><span class="style4">sizeof</span><span class="style3"> operator in Chapter 8.
The </span><span class="style4">new</span><span class="style3"> and </span><span class="style4">delete</span><span class="style3"> operators provided by Think C and C++ are discussed in Chapter 4. Think C allows these operators to be customized*, while C++ includes the ability to customize other operators as well. This "overloading" feature is not discussed here.
This chapter begins with a discussion on C expressions and introduces the arithmetic and logical operators, type conversion, and (briefly) bit manipulation.
</span></text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>70105</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>Allocators & deallocators</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>Allocators & deallocators - p157</text>
</content>
<name></name>
<script></script>
</card>
card_45494.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
C expressions occur as assignments, function arguments, and as part of other statements discussed in Chapter 6.
All C operators — including the assignment</span><span class="style4"> = </span><span class="style3">and logical operators — can be mixed freely in expressions (with appropriate type conversion). This affords great flexibility in program style and structure, although care must be exercised to avoid excessively complex constructs which may lead to programming errors and obscure code.
The associativity of most operators is left to right, with the exception of the assignment operators.
The order of evaluation of operators within an expression is given in the following chart (adapted from Kernighan and Ritchie's*) although parentheses can be used to force the desired order of evaluation.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>165</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>2231</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>Bibliography</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>Bibliography - p259</text>
</content>
<name></name>
<script></script>
</card>
card_45796.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">s expected, the multiplication</span><span class="style4"> * </span><span class="style3">and division</span><span class="style4"> / </span><span class="style3">operators have precedence over the addition</span><span class="style4"> + </span><span class="style3">and subtraction</span><span class="style4"> - </span><span class="style3">operators. The modulus operator</span><span class="style4"> % </span><span class="style3">produces the remainder when its integer operands divide each other. No exponentiation operator is provided. The standard math library function </span><span class="style4">pow()</span><span class="style3"> serves this purpose.*
One source of occasional programming errors is that arithmetic operations involving only integer values produce an integer result. In the following example, the float variable </span><span class="style4">f</span><span class="style3"> is initialized with the value 0 whereas </span><span class="style4">g</span><span class="style3"> is assigned .5 (recall that constants must contain a decimal point to be considered floating-point numbers).
</span><span class="style4">
float f = 1/2; // assigns 0 to f
float g = 1./2.;
</span><span class="style3">The unary (one-operand) negation operator</span><span class="style4"> - </span><span class="style3">has higher precedence than the foregoing operators, as do the unary increment</span><span class="style4"> ++ </span><span class="style3">and decrement</span><span class="style4"> -- </span><span class="style3">operators. These last operators are a shorthand for assigning the value of a variable incremented or decremented by 1 to the same variable. As with other assignment operators, the change to the value of the variable is considered a "side effect", since</span></text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>34612</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>pow() function</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>pow() function - p215</text>
</content>
<name></name>
<script></script>
</card>
card_45919.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">valuating the part of the expression containing the operator yields a usable value as well. The</span><span class="style4"> ++ </span><span class="style3">and</span><span class="style4"> -- </span><span class="style3">operators may be used in prefix form (preceding the operand) or in postfix form (following the operand) depending on whether the variable should be incremented/decremented </span><span class="style7">before</span><span class="style3"> evaluation or </span><span class="style7">after</span><span class="style3"> evaluation. For example, the following expression increments both </span><span class="style4">a</span><span class="style3"> and </span><span class="style4">b</span><span class="style3"> yet assigns </span><span class="style4">(a+1)</span><span class="style3"> times </span><span class="style4">b</span><span class="style3"> to </span><span class="style4">c</span><span class="style3">:
</span><span class="style4">
c = ++a * b++;
</span><span class="style3">C also provides shorthand operators for assigning to a variable the effect of adding, subtracting, multiplying, dividing, or taking the integer remainder of this variable with another value. The following demonstrates the advantages in efficiency and clarity afforded by these operators:
f_array[index_function(i,j,k)] += x; // using shorthand operator
</span><span class="style3">The first statement requires evaluation of </span><span class="style4">index_function()</span><span class="style3"> twice, and requires the </span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>168</text>
</content>
<name></name>
<script></script>
</card>
card_47517.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">erson reading the code to ascertain that indeed this statement simply increments a single array element by </span><span class="style4">x</span><span class="style3">.</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>169</text>
</content>
<name></name>
<script></script>
</card>
card_44647.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">ogical expressions in C yield a value of 1 (true) or 0 (false). For example:
</span><span class="style4">
result = 5 > 6;
</span><span class="style3">Since the assignment operator</span><span class="style4"> = </span><span class="style3">has very low precedence, the logical expression </span><span class="style4">5>6</span><span class="style3"> is evaluated first, and the value 0 (false) is assigned to the integer variable </span><span class="style4">result</span><span class="style3">. To distinguish it from the assignment operator, the logical operator for equality uses two equal signs:</span><span class="style4"> ==</span><span class="style3">. </span><span class="style7">A very common programming error is to use the ssignment operator where the equality operator was intended.</span><span class="style3"> For example, the programmer expected the condition in the following </span><span class="style4">if</span><span class="style3"> statement to be true, since the value of "</span><span class="style4">a==0</span><span class="style3">" would be 1. However, since the value of an assignment expression is the value which was assigned, the value of "</span><span class="style4">a = 0</span><span class="style3">" is 0 and the condition is false. Note that the expression is still legal, so no compilation error is generated.
</span><span class="style4">
int a = 0;
if (a = 0) // 'a == 0' was intended
.
.
</span><span class="style3">
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>170</text>
</content>
<name></name>
<script></script>
</card>
card_46228.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">he "not equal to" operator in C is</span><span class="style4"> !=</span><span class="style3">, the "not" operator is</span><span class="style4"> !</span><span class="style3">, the "and" operator is </span><span class="style4">&&</span><span class="style3">, and the "or" operator is</span><span class="style4"> ||</span><span class="style3">. The condition in the following</span><span class="style4"> if </span><span class="style3">statement is true:
</span><span class="style4">
if (!(4==5) && 6!=7)
.
.
</span><span class="style3">In English, it says: "if four equals five is </span><span class="style7">not</span><span class="style3"> true, </span><span class="style7">and</span><span class="style3"> six does not equal seven...".
As a shorthand for the</span><span class="style4"> if </span><span class="style3">statement*, C provides the ternary (three-operand) conditional operator</span><span class="style4"> ?:</span><span class="style3">. The value of an expression using this operator depends upon the value of its first operand. If the first operand is true (non-zero), then the second operand is evaluated; else, the third is evaluated and becomes the value of the expression. The operator may be mixed freely with other operators. For example, the following assigns the value 12 to </span><span class="style4">result</span><span class="style3">:
</span><span class="style4">
result = ((5==6) ? 5 : 6) * 2;</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>171</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>48179</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>if-else statement</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>if-else statement - p180</text>
</content>
<name></name>
<script></script>
</card>
card_44917.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
C attempts to preserve the value of an expression when mixed with an expression or variable of another type. As was seen in Chapter 2, chars are automatically converted to ints in mixed arithmetic expressions. During arithmetic involving both ints and doubles, ints are "promoted" to double, as are floats when mixed with doubles.
In fact, previous to ANSI C, all expressions involving floats were converted to double. ANSI C allows single-precision arithmetic operations when all operands are float.
When an assignment operator is used, the value of the right side is converted to the type of the left side where possible. High-order bits in an int are discarded when converted to char, if necessary. The fractional part of a float is discarded when converted to int. A double is rounded when converting to float.
As discussed later in this section, values may be explicitly converted to another type
</text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>172</text>
</content>
<name></name>
<script></script>
</card>
card_47733.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text>by the programmer, to supercede the automatic type conversion rules. In fact, explicit type conversion is frequently used even when the automatic rules have the same effect, in order to clarify the evaluation of mixed expressions.
</text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>173</text>
</content>
<name></name>
<script></script>
</card>
card_46937.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">UNCTION PROTOTYPES FOR TYPE CONVERSION
Traditionally, C's absence of run-time type checking contributed to its efficiency and flexibility but could also be the source of much programming frustration. When a value was passed as a function argument, its type was not converted automatically to the type expected by the function. Thus a call to the</span><span class="style4"> sqrt() </span><span class="style3">math library function of the form:
</span><span class="style4">
result = sqrt(10); // bad result using pre-ANSI C
</span><span class="style3">returned an incorrect result since an int argument was passed to a function expecting a double.
With the advent of function prototypes* in ANSI C (and TC and C++), automatic type conversion was extended to such cases. That is, by stating the types of the arguments expected by a function before that function is called, a function prototype gives the compiler enough information to provide the needed type conversion.
</span></text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>12248</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>Function prototypes</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>Function prototypes - p94</text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>174</text>
</content>
<name></name>
<script></script>
</card>
card_47191.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
</span><span class="style3">Explicit type conversion is performed using the </span><span class="style7">cast</span><span class="style3"> operator. A value is "cast" to another type by prefixing it with the desired type enclosed in parentheses. For example, to ensure that floating-point rather than integer arithmetic is used, it may be desirable to cast an integer variable to a float in an arithmetic expression. In this case,</span><span class="style4"> f </span><span class="style3">is assigned the value 0 while</span><span class="style4"> g </span><span class="style3">is assigned 0.5:
</span><span class="style4">
int a = 1,
b = 2;
float f,g;
f = a / b;
g = (float) a / b;
</span><span class="style3">The cast operator has higher precedence than arithmetic operators, so the value of</span><span class="style4"> a</span><span class="style3"> is converted to a float before the division takes place.
</span><span class="style4">
</span><span class="style3">In TC and C++ casts are often used to inform the compiler of the class of an object reference.*</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>175</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>69198</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>Casting object references</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>Casting object references - p131</text>
</content>
<name></name>
<script></script>
</card>
card_45309.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">o fulfill its original role as a "low-level" (but extensible) language suited for writing operating systems, C provides numerous operators for bit manipulation. Operands for these operators must be integral types. For this purpose, integral values may be assigned using octal constants, which contain a leading zero:
<text><span class="style3">he simplest C statement is the </span><span class="style7">null statement</span><span class="style3">, a lone semicolon. This is occasionally used when a loop body does not require any expressions, as shown later in this chapter. An </span><span class="style7">expression statement</span><span class="style3"> is an expression followed by a semicolon:
</span><span class="style4">
2 + 2; // useless statement
</span><span class="style3">Notice that the value of the expression is ignored. A more useful such statement is one whose expression has a "side effect" like assigning a value or evaluating a function!
</span><span class="style4">
int a; // declaration
a = 2 + 2;
printf("result: %d\n",a);
</span><span class="style3">This chapter begins with a discussion on grouping expression statements and goes on to discuss C's control flow statements for conditional execution and looping. The </span><span class="style4">return</span><span class="style3"> statement to terminate a function was already discussed in Chapter 3.
</span></text>
</content>
<name></name>
<script></script>
</card>
card_49867.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
A group of statements enclosed in curly</span><span class="style4"> {} </span><span class="style3">braces is a compound statement or "block". (The closing brace should not generally be followed by a semicolon. If it is, then the semicolon is considered a separate null statement.) Compound statements are used for function bodies, user-defined data types, and anywhere the language syntax requires a statement as will be seen in this chapter.
In particular, a block may be </span><span class="style7">nested</span><span class="style3"> within another block, and may contain declarations of variables local to the inner block. This construct is rarely used, since creating a separate function to accomplish the processing of the inner block usually improves code readability and modularity.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>178</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p215</text>
</content>
<name></name>
<script></script>
</card>
card_50052.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
A sequence of expression statements may be rewritten as a single statement, where the individual expressions are separated by the comma operator. Evaluation is from left to right, and the value of the statement (ignored in the following example) is that of the rightmost expression.
</span><span class="style4">
temp = i , i = j , j = temp; // swap i and j values
</span><span class="style3">As with nested blocks this construct should be used sparingly and with care to avoid obscuring program structure. The comma operator most often finds use in conjunction with the </span><span class="style4">while</span><span class="style3"> and </span><span class="style4">for</span><span class="style3"> loops discussed later in this chapter.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>179</text>
</content>
<name></name>
<script></script>
</card>
card_48179.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">tatements are executed conditionally using C's</span><span class="style4"> if </span><span class="style3">statement. Its syntax is simply:
</span><span class="style4">
if (expression)
statement1
else
statement2
</span><span class="style3">where the </span><span class="style4">else</span><span class="style3"> clause is optional. If the expression is non-zero (true) then </span><span class="style4">statement1</span><span class="style3"> is executed, else </span><span class="style4">statement2</span><span class="style3"> (if present) is executed. The statements may be simple expression statements or compound statements. For clarity it is important to indent the statements (typically one tab stop or 4 characters).
Since C is permissive about the use of "white space" (spaces, tabs, new-line characters), there are several popular placements for the opening and closing braces of compound statements. Some programmers place the opening brace at the end of the line containing the </span><span class="style4">if</span><span class="style3"> and </span><span class="style4">else</span><span class="style3"> statements, while others prefer to indent both the opening and closing braces by the same amount as in the example below.</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>180</text>
</content>
<name></name>
<script></script>
</card>
card_50308.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">hen </span><span class="style4">if</span><span class="style3"> statements are nested the </span><span class="style4">else</span><span class="style3"> clause is by default associated with the closest </span><span class="style4">if</span><span class="style3"> statement. Braces can be used to force a different association:
</span><span class="style4">
if (i < 10)
{
if (j == i)
done = 1;
}
else
done = 1;
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>181</text>
</content>
<name></name>
<script></script>
</card>
card_50447.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
The "else if" statement available in other languages is easily simulated using nested </span><span class="style4">if</span><span class="style3"> statements and the appropriate use of white space:
</span><span class="style4">
if (i == 0)
result = 'a';
else if (i == 1 || i == 2)
result = 'b';
else if (i == 3)
result = 'c';
else
result = 'd';
</span><span class="style3">An alternative which is often appropriate is the </span><span class="style4">switch</span><span class="style3"> statement discussed in the next section.</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>182</text>
</content>
<name></name>
<script></script>
</card>
card_48576.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">he </span><span class="style4">switch</span><span class="style3"> statement accomplishes a multiway decision based on comparison of an expression with several alternative constant values. The statements following each </span><span class="style4">case</span><span class="style3"> label are executed when the value of the tested expression matches the associated constant. The </span><span class="style4">default</span><span class="style3"> label indicates the processing if no match is found.
</span><span class="style4">
switch (i)
{
case 0: result = 'a';
break;
case 1: // "fall through" to processing for case 2
case 2: result = 'b';
break;
case 3: result = 'c';
break;
default: result = 'd';
break;
}
</span><span class="style3">
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>183</text>
</content>
<name></name>
<script></script>
</card>
card_50849.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3"> </span><span class="style4">break</span><span class="style3"> statement is used to cause an immediate exit from the </span><span class="style4">switch</span><span class="style3"> body. Without it execution will continue with the statements following the remaining cases. The example above has the same effect as the "else if" example from the previous section, and demonstrates judicious use of </span><span class="style4">break</span><span class="style3"> statements.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>184</text>
</content>
<name></name>
<script></script>
</card>
card_48901.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">he </span><span class="style4">while</span><span class="style3"> statement implements a loop whose statement (or compound statement) is repeated until the conditional expression evaluates to 0 (false):
</span><span class="style4">
while (expression)
statement
</span><span class="style3">In the following example the null statement is used, since the side effect of evaluating the expression implements all the desired processing:
</span><span class="style4">
while (!mouse_button_is_down())
;
</span><span class="style3">An interesting application of the comma operator mentioned earlier in this chapter is to evaluate a sequence of expressions in place of the usual condition. The expressions are evaluated left to right, and the loop continues until the rightmost expression is false. In the following example the side effect of the leftmost expression is assigning a value to the character variable </span><span class="style4">c</span><span class="style3">. (The standard library function </span><span class="style4">getchar()</span><span class="style3"> returns the next character from the standard input device.)
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>185</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p223</text>
</content>
<name></name>
<script></script>
</card>
card_51117.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style4"> while (c = getchar() , c != 'x')
process_input(c);
</span><span class="style3">The alternative</span><span class="style4"> do-while </span><span class="style3">statement evaluates the expression after having executed the statement once:
</span><span class="style4">
do
statement
while (expression);
</span><span class="style3">(Note the trailing semicolon.) Though used less frequently than</span><span class="style4"> while </span><span class="style3">or</span><span class="style4"> for </span><span class="style3">loops, there are occasional situations where</span><span class="style4"> do-while </span><span class="style3">affords simplified code.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>186</text>
</content>
<name></name>
<script></script>
</card>
card_51294.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
The </span><span class="style4">break</span><span class="style3"> statement may be used within the compound statement representing the loop body, to cause immediate exit from the loop. It is usually used in conjunction with an</span><span class="style4"> if-else </span><span class="style3">statement to conditionally exit the loop. It should be used with care, since program clarity may be compromised when the control of the loop is no longer localized in the main loop condition expression. Consider the following example:
</span><span class="style4">
while (i < 10)
{
if (position[i] > 1000)
break;
printf("Position is: %d\n",position[i++]); // increment operator '++'
}
</span><span class="style3">Instead, it may be preferable to include the break condition into the main loop condition:
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>187</text>
</content>
<name></name>
<script></script>
</card>
card_51507.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style4"> while (i < 10 && position[i] <= 1000)
printf("Position is: %d\n",position[i++]);
</span><span class="style3">Here is another alternative to </span><span class="style4">break</span><span class="style3"> which improves code clarity when an unusual condition may arise during the loop:
</span><span class="style4">
too_big = 0;
while (i < 10 && !too_big)
{
if (position[i] <= 1000)
printf("Position is: %d\n",position[i++]);
else
too_big = 1;
}
</span><span class="style3">The </span><span class="style4">continue</span><span class="style3"> statement is syntactically similar to </span><span class="style4">break</span><span class="style3"> but instead causes the next iteration of the loop to commence immediately. Again, in many cases code clarity can be improved by instead using appropriate conditional expressions.</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>188</text>
</content>
<name></name>
<script></script>
</card>
card_49349.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">he </span><span class="style4">for</span><span class="style3"> loop is highly flexible. Its syntax is:
</span><span class="style4">
for (expression1 ; expression2 ; expression3)
statement
expression1</span><span class="style3"> is evaluated once upon entry to the loop, the statement is executed if </span><span class="style4">expression2</span><span class="style3"> evaluates to nonzero (true), and </span><span class="style4">expression3</span><span class="style3"> is evaluated at the end of each iteration of the loop. Most commonly, </span><span class="style4">expression1</span><span class="style3"> is used as the loop initialization, </span><span class="style4">expression2</span><span class="style3"> as the loop condition, and </span><span class="style4">expression3</span><span class="style3"> to increment a loop counter. For example:
</span><span class="style4">
for (i=0 ; i<10 ; i++)
process_things(i);
</span><span class="style3">The comma operator is useful to implement multiple counters:
</span><span class="style4">
for (i=0,j=10 ; i<10 ; i++,j--)
process_things(i,j);
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>189</text>
</content>
<name></name>
<script></script>
</card>
card_49620.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">he </span><span class="style4">goto</span><span class="style3"> statement allows unconditional transfer to a labeled statement. The labelled statement must occur in the same function body (actually the same statement block). For example:
</span><span class="style4">
.
.
goto begin_output;
.
.
begin_output: // label
printf("Here's the output:\n");
.
.
goto</span><span class="style3"> statements and labels are almost never used since they tend to obscure program structure making debugging and maintenance difficult. Code using </span><span class="style4">goto</span><span class="style3"> can always be rewritten using structured programming constructs like</span><span class="style4"> if-else</span><span class="style3"> and </span><span class="style4">while</span><span class="style3">.</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>190</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p62</text>
</content>
<name></name>
<script></script>
</card>
card_21485.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">he C </span><span class="style7">preprocessor</span><span class="style3"> performs various text-manipulation functions on source files as a first step in the compilation process. This chapter describes how to use the preprocessor to accomplish text substitution with and without parameters, file inclusion, and conditional compilation of selected portions of the source file.
Think C provides a "Preprocess" option to allow the programmer to see the effects of preprocessor directives.
</span></text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p62</text>
</content>
<name></name>
<script></script>
</card>
card_51878.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">reprocessor directives are identified by beginning with the</span><span class="style4"> # </span><span class="style3">symbol, and are generally not indented beyond the first column. A trailing semicolon is </span><span class="style7">not</span><span class="style3"> used.
</span><span class="style7">Text substitution</span><span class="style3">, or macro substitution, is performed using the</span><span class="style4"> #define </span><span class="style3">directive in the following syntax, usually located at the beginning of the source file:
</span><span class="style4">
# define NAME replacement text // no trailing semicolon!
</span><span class="style3">Before compilation the preprocessor will replace all occurrences of </span><span class="style4">NAME</span><span class="style3"> in the source file with the replacement text. The name to be replaced follows the same rules as for C variable and function identifiers. By convention this is nearly always capitalized, to avoid confusion with other variable and function identifiers. There are very few grammatical restrictions on the replacement text.
One of the most common uses of macro substitution is naming constants, as demonstrated below. Note, however, that with the advent of the </span><span class="style4">const</span><span class="style3"> qualifier in ANSI C, there is an alternative way to identify symbolic constants.*
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>192</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>70575</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>const qualifier</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>const qualifier - p62</text>
</content>
<content>
<layer>background</layer>
<id>18</id>
<text>p66</text>
</content>
<name></name>
<script></script>
</card>
card_52640.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
</span><span class="style3">The programmer may then use the names </span><span class="style4">TRUE</span><span class="style3"> and </span><span class="style4">FALSE</span><span class="style3"> in his/her source file, confident that these will be replaced with the constants 1 and 0 upon compilation:
</span><span class="style4">
done = FALSE;
while (!done)
{
if ((c = getchar()) == 'x')
done = TRUE;
else
.
.
}
</span><span class="style3">It is good programming practice to use this technique whenever a numerical constant is used, to help identify the purpose of this constant and to simplify future changes:
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>193</text>
</content>
<name></name>
<script></script>
</card>
card_53025.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text>Such macros can be used to extend the C language or even to write C programs using the syntax of another language entirely. This is rarely done, however, since the source code becomes confusing to other programmers and more difficult to debug.
</text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>195</text>
</content>
<name></name>
<script></script>
</card>
card_53649.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">ACRO SUBSTITUTION WITH PARAMETERS
Macros may be defined using parameters as well. In this case the text passed as an "argument" is placed into the replacement text everywhere the parameter appears:
</span><span class="style4">
# define SQUARE(x) x * x // don't use this version!
.
.
f_array[i] = SQUARE(f_array[i]);
</span><span class="style3">After preprocessing, the "call" to the </span><span class="style4">SQUARE()</span><span class="style3"> macro expands to:
</span><span class="style4">
f_array[i] = f_array[i] * f_array[i];
</span><span class="style3">However, there is a serious deficiency with the </span><span class="style4">SQUARE()</span><span class="style3"> macro defined above. An expression like "</span><span class="style4">c = 1./SQUARE(a + b)</span><span class="style3">" expands to "</span><span class="style4">c = 1./a + b * a + b</span><span class="style3">". Due to the arithmetic precedence rules, this does not produce the desired result. The preprocessor performs text substitution without regard for rules of C syntax. The</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>196</text>
</content>
<content>
<layer>background</layer>
<id>18</id>
<text>p207</text>
</content>
<name></name>
<script></script>
</card>
card_53898.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">olution is to define an improved version of this macro:
</span><span class="style4">
# define SQUARE(x) ((x) * (x))
</span><span class="style3">In conclusion, it is generally wise to </span><span class="style7">enclose each occurence of the parameter in the replacement text with parentheses, and enclose the entire replacement text with parentheses</span><span class="style3">.
Macros with parameters may be more efficient than genuine functions which perform the same task, by eliminating the need for argument passing, variable allocation, etc. On the other hand, the argument "passed" to a macro must be evaluated once for each occurence of the parameter in the replacement text. If the argument is an expression which is difficult to evaluate, the macro may be </span><span class="style7">less</span><span class="style3"> efficient than an equivalent function. For example, consider the "call":
</span><span class="style4">
result = SQUARE( sqrt(SQUARE(sin(x))+SQUARE(cos(x)))+1. );
</span><span class="style3">The expression "passed" is evaluated twice after expansion of the macro.</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>197</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p8</text>
</content>
<name></name>
<script></script>
</card>
card_54588.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text>Worse still, if the expression passed has side effects, such as an assignment expression, then the multiple evaluations may have particularly damaging results. Therefore, expressions producing side effects should not be passed as "arguments" to macros.
</text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>198</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p8</text>
</content>
<name></name>
<script></script>
</card>
card_52189.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">s mentioned earlier in this text, it is frequently convenient to place a list of declarations of user-defined data types and functions (as well as </span><span class="style4">#defined</span><span class="style3"> names) in a separate "header" file which may be accessed by various other source files. This is accomplished with the </span><span class="style7">file inclusion</span><span class="style3"> preprocessor directive, usually placed at the beginning of a source file. Its syntax is one of:
</span><span class="style4">
# include <standard library header file>
# include "user-defined header file"
</span><span class="style3">This directs the preprocessor to replace the </span><span class="style4">#include</span><span class="style3"> line with all the text contained in the named file. Using quotes instead of</span><span class="style4"> <> </span><span class="style3">braces instructs the preprocessor to look for the file in the user's directory rather than that used by the system for standard header files. For example, a source file using the</span><span class="style4"> printf() </span><span class="style3">standard library function declared in the standard header </span><span class="style18">stdio.h</span><span class="style3"> and the user-defined type </span><span class="style4">personnel_rec</span><span class="style3"> defined in the user's file </span><span class="style18">personnel.h</span><span class="style3"> should begin with:
</span><span class="style4">
# include <stdio.h>
# include "personnel.h"
</span><span class="style3">
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>199</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p189</text>
</content>
<name></name>
<script></script>
</card>
card_54204.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">y convention header files use the extension "</span><span class="style18">.h</span><span class="style3">" rather than the "</span><span class="style18">.c</span><span class="style3">" extension for C source files. While header files may contain any legal C code, it is good practice to limit this code to variable and function declarations and preprocessor directives. If an external variable is defined (allocated) or a complete function definition is given,
then errors may occur when the overall program is linked (i.e., when the compiled source files and the standard function libraries are combined into an executable application). The reason is that the header may need to be</span><span class="style4"> #included </span><span class="style3">into several source files, leading to multiple definitions for the same variable or function.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>200</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p249</text>
</content>
<name></name>
<script></script>
</card>
card_54516.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
When taking advantage of the ability to define classes in Think C and C++, it is common practice to place each class definition in a header file, and the definitions of the member functions of the class in a separate source file. In the example in Chapter 4 the </span><span class="style4">Person</span><span class="style3"> class was defined in </span><span class="style18">person.h</span><span class="style3"> and its methods in </span><span class="style18">person.c</span><span class="style3">. The source file </span><span class="style4">#includes</span><span class="style3"> the corresponding header, as do all files which make use of the </span><span class="style4">Person</span><span class="style3"> class definition; namely </span><span class="style18">student.h</span><span class="style3"> and </span><span class="style18">main.c</span><span class="style3">.
</span><span class="style4">
</span><span class="style3">Notice that </span><span class="style18">main.c</span><span class="style3"> </span><span class="style4">#includes</span><span class="style3"> </span><span class="style18">student.h</span><span class="style3"> as well. This suggests that the contents of </span><span class="style18">person.h</span><span class="style3"> are included twice in </span><span class="style18">main.c</span><span class="style3">, producing an error due to duplicate definition. To avoid this, Think C allows the programmer to place the directive:
</span><span class="style4">
# pragma once // Think C only
</span><span class="style3">at the beginning of the header </span><span class="style18">person.h</span><span class="style3">. This ensures the file's contents are compiled only once. A </span><span class="style4">#pragma</span><span class="style3"> directive is one which is defined only for a particular compiler. C++ conditional compilation must be made explicitly, as discussed in the
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>201</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p249</text>
</content>
<name></name>
<script></script>
</card>
card_54839.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
Occasionally this arrangement may lead to difficulties. Consider a circular definition involving two classes:
</span><span class="style4">
struct Person:Generic_Class
{
Parent *parent_ptr;
.
.
};
struct Parent:Person
{
.
.
};
</span><span class="style3">The </span><span class="style4">Person</span><span class="style3"> class contains an instance variable which is a pointer to a </span><span class="style4">Parent</span><span class="style3"> object, and the </span><span class="style4">Parent</span><span class="style3"> class is descended from the </span><span class="style4">Person</span><span class="style3"> class. (This makes sense, since a </span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>202</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p249</text>
</content>
<name></name>
<script></script>
</card>
card_55248.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">arent is a type of person, yet each person has a parent.)
Suppose these classes are defined in the header files </span><span class="style18">person.h</span><span class="style3"> and </span><span class="style18">parent.h</span><span class="style3">, each of which contains conditional compilation directives to prevent multiple inclusion. The header </span><span class="style18">person.h</span><span class="style3"> must </span><span class="style4">#include</span><span class="style3"> </span><span class="style18">parent.h</span><span class="style3"> to compile properly, which in turn must </span><span class="style4">#include</span><span class="style3"> </span><span class="style18">person.h</span><span class="style3">! However, since by this point </span><span class="style18">person.h</span><span class="style3"> has already begun compilation the conditional compilation feature will prevent its reinclusion. This will prevent the successful compilation of files </span><span class="style4">#including</span><span class="style3"> these headers.
</span><span class="style4">
</span><span class="style3">Instead, the following technique may be used. One of the two headers — </span><span class="style18">parent.h</span><span class="style3"> — may be written as usual, with a directive to </span><span class="style4">#include</span><span class="style3"> </span><span class="style18">person.h</span><span class="style3"> at the beginning of the file. At the beginning of the file </span><span class="style18">person.h</span><span class="style3"> must contain the line:
</span><span class="style4">
struct Parent; // inform the compiler that Parent is a struct "tag"
</span><span class="style3">This "tag" declaration is sufficient to complete the circular definition of the </span><span class="style4">Person</span><span class="style3"> class, as long as references to "</span><span class="style4">Parent</span><span class="style3">" in this header are replaced by "</span><span class="style4">struct Parent</span><span class="style3">". However, a source file which </span><span class="style4">#includes</span><span class="style3"> </span><span class="style18">person.h</span><span class="style3"> might require a complete </span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>203</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p249</text>
</content>
<name></name>
<script></script>
</card>
card_47917.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">efinition of the </span><span class="style4">Parent</span><span class="style3"> class. This is ensured by placing a directive to </span><span class="style4">#include</span><span class="style3"> </span><span class="style18">parent.h</span><span class="style3"> at the </span><span class="style7">end</span><span class="style3"> of the file </span><span class="style18">person.h</span><span class="style3">.
If the </span><span class="style4">class</span><span class="style3"> keyword is used in place of </span><span class="style4">struct</span><span class="style3"> to define these classes, then a similar approach is taken. The line
</span><span class="style4">
class Parent; // inform the compiler that Parent is a class
</span><span class="style3">is placed at the beginning of the file </span><span class="style18">person.h</span><span class="style3"> in lieu of </span><span class="style4">#including</span><span class="style3"> </span><span class="style18">parent.h</span><span class="style3">. The header </span><span class="style18">parent.h</span><span class="style3"> is </span><span class="style4">#included</span><span class="style3"> at the </span><span class="style7">end</span><span class="style3"> of </span><span class="style18">person.h</span><span class="style3">. In this case, it is </span><span class="style7">not</span><span class="style3"> necessary to replace all references to "</span><span class="style4">Parent</span><span class="style3">" in </span><span class="style18">person.h</span><span class="style3"> with "</span><span class="style4">class Parent</span><span class="style3">".</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>204</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p249</text>
</content>
<name></name>
<script></script>
</card>
card_52411.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">ften it is desired that a program compile correctly under two or more different circumstances. In such cases, it is convenient to write a single collection of source and header files, using preprocessor directives to ensure correct compilation for the respective circumstances. The syntax:
</span><span class="style4">
# define NAME // no replacement text given
</span><span class="style3">is used to "define" a name for use with the </span><span class="style7">conditional compilation</span><span class="style3"> directives:
</span><span class="style4">
# ifdef NAME
.
.
# else
.
.
# endif
</span><span class="style3">If</span><span class="style4"> NAME </span><span class="style3">has been "defined" before the</span><span class="style4"> #ifdef </span><span class="style3">directive is encountered, then the
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>205</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p249</text>
</content>
<name></name>
<script></script>
</card>
card_55372.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">ource code between the</span><span class="style4"> #ifdef </span><span class="style3">and the</span><span class="style4"> #else </span><span class="style3">(if present) is compiled. Otherwise the source code between</span><span class="style4"> #else </span><span class="style3">and</span><span class="style4"> #endif </span><span class="style3">is compiled. The programmer places source code appropriate to only one circumstance following the</span><span class="style4"> #ifdef </span><span class="style3">and code for the other circumstance following the</span><span class="style4"> #else</span><span class="style3">. Thus, with only a single change — incorporation of the appropriate</span><span class="style4"> #define </span><span class="style3">directive — source code appropriate to the chosen circumstance may be compiled.
For example, it may be desired that a program compile under two slightly different C compilers, having different names for the header file for standard string functions:
</span><span class="style4">
# define CCOMP1 // remove this line for alternate compiler
.
.
# ifdef CCOMP1
# include <string.h>
# else
# include <strings.h>
# endif</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>206</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p8</text>
</content>
<name></name>
<script></script>
</card>
card_56532.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">nother use of conditional compilation is to avoid reinclusion of header files which are themselves</span><span class="style4"> #included </span><span class="style3">into other headers, a common problem in object-oriented programs. (TC provides a simpler method to accomplish this.*) For a header file named </span><span class="style18">filename.h</span><span class="style3">, a common approach is to begin the file with:
</span><span class="style4">
# ifndef filename_h // like #ifdef, but means "if not defined"
# define filename_h
</span><span class="style3">and end the file with:
</span><span class="style4">
# endif
</span><span class="style3">Also, note that it is legal to nest</span><span class="style4"> #ifdef/#endif </span><span class="style3">conditions.
Certain names are</span><span class="style4"> #defined </span><span class="style3">automatically by the compiler in use. For example, the name </span><span class="style4">THINK_C</span><span class="style3"> is defined whenever the TC compiler is used. Conditional compilation based on automatically-defined names can help improve portability by restricting compilation of non-standard portions of the code to specific compilers.</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>207</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>54516</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>TC feature to prevent header reinclusion</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>TC feature to prevent header reinclusion - p201</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p8</text>
</content>
<name></name>
<script></script>
</card>
card_21751.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">'s efficiency is granted in part by its stripped-down design. At the same time, C is made extremely powerful and flexible by the addition of </span><span class="style7">standard function libraries</span><span class="style3"> for input/output, mathematics, string manipulation, and memory management. Programs making use solely of these functions are generally portable (or can be made so with judicious use of conditional compilation*). In Think C the ANSI library contains all these standard functions.
In addition, many C compilers provide specialized function libraries appropriate to the intended hardware or application area. These further enhance the language's power while compromising portability. TC's MacTraps library actually consists of calls to the Macintosh ROM "Toolbox" routines which accomplish the graphical user interface and many other functions. This "library" allows Macintosh C programmers to call these routines as though they were C functions. Appendix 1 describes using libraries with TC projects.
Programmers may also create their own libraries of related, frequently-used routines.
</span></text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>52411</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>Conditional compilation</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>Conditional compilation - p205</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p223</text>
</content>
<name></name>
<script></script>
</card>
card_56733.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">sually the functions defined in standard, specialized, or user-defined libraries are declared (their prototypes are given) in header files. The appropriate header should be </span><span class="style4">#included</span><span class="style3"> into any source file accessing these functions.* Note that some functions are implemented as macros in the standard header file.
(In truth, the user may provide the appropriate function prototypes himself/herself instead of </span><span class="style4">#including</span><span class="style3"> the standard header file. This is a dangerous practice since future versions of the compiler may change the function implementation slightly, causing the user's prototype to be inaccurate. Portability is also jeapordized.)
This chapter describes only a sampling of frequently-used functions from the standard C function libraries. A C reference text or manual should be consulted for greater breadth and detail. Consult the documentation for your own compiler to see what specialized libraries are available, if portability is not crucial.
The object-oriented nature of Think C and C++ encourages the use of </span><span class="style7">class libraries</span><span class="style3"> instead of or in addition to function libraries. These are discussed in Chapter 9.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>209</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>52189
</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>File inclusion
</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>File inclusion - p199</text>
</content>
<name></name>
<script></script>
</card>
card_33614.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">'s standard I/O (input/output) functions are contained in the ANSI library. The standard header file </span><span class="style18">stdio.h</span><span class="style3"> contains declarations for these functions; i.e., any source file which uses standard I/O functions should contain the preprocessor directive:
</span><span class="style4">
# include <stdio.h>
</span><span class="style3">In practice, professional Macintosh C programs often call the Macintosh Toolbox routines (via the MacTraps specialized library) to accomplish the user interface rather than use the standard I/O library. This technique produces efficient but non-portable programs which take full advantage of the Macintosh's hardware capabilities. Nonetheless, the standard I/O functions are useful for producing portable programs where a command-line user interface is tolerated.
The standard ANSI I/O functions treat input and output as "streams" of bytes or characters, which are written to and read from binary or text files or I/O devices. The procedure for addressing such a file or device is: first "open" the stream; then perform I/O; then "close" the stream.</span></text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p223</text>
</content>
<name></name>
<script></script>
</card>
card_57294.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
Three streams are automatically opened when a C program begins execution: stdin, stdout, and stderr. These represent the standard input device, standard output device, and the device for reporting errors, respectively.
By default these devices usually refer to the user's terminal. TC automatically creates a "console" text window on the Macintosh when a function refers to one of these streams. (On UNIX systems these streams can be "redirected" to refer to text files, and this may be emulated on the Macintosh using TC's</span><span class="style4"> ccommand() </span><span class="style3">function.)
The powerful </span><span class="style4">printf()</span><span class="style3"> and </span><span class="style4">scanf()</span><span class="style3"> standard functions write to and read from the standard output and standard input devices. Their prototypes are:
</span><span class="style4">
int printf(const char *format, ...); // variable number of arguments
int scanf(const char *format, ...);
</span><span class="style3">The format string contains conversion codes such as </span><span class="style4">%d</span><span class="style3"> (integer value), </span><span class="style4">%ld</span><span class="style3"> (long </span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>211</text>
</content>
<name></name>
<script></script>
</card>
card_57526.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">nteger), </span><span class="style4">%c</span><span class="style3"> (character), </span><span class="style4">%s</span><span class="style3"> (string), </span><span class="style4">%g</span><span class="style3"> (float), </span><span class="style4">%lg</span><span class="style3"> (double). The format string in </span><span class="style4">printf()</span><span class="style3"> may contain text mixed with the format codes. Following the format string is a variable number of arguments, each of which corresponds to a conversion code in the format string. For </span><span class="style4">printf()</span><span class="style3"> these arguments are values to be written to stdout, while for </span><span class="style4">scanf()</span><span class="style3"> they should be the addresses of the variables into which values from stdin will be read.
Chapters 1, 3, and 4 contain numerous examples of the use of </span><span class="style4">printf()</span><span class="style3"> and </span><span class="style4">scanf()</span><span class="style3">.</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>212</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p212</text>
</content>
<name></name>
<script></script>
</card>
card_57613.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
To read from and write to files, the appropriate stream should first be opened via the standard library function</span><span class="style4"> fopen()</span><span class="style3">, whose prototype is:
</span><span class="style3">The filename and description arguments specify the name of the file and how it will be used, such as "r" for reading a text stream and "w" for writing to a text stream. The return value is a pointer to a </span><span class="style4">FILE</span><span class="style3"> type: a data structure defined in </span><span class="style18">stdio.h</span><span class="style3"> identifying the characteristics of the I/O device specified.
The</span><span class="style4"> fprintf()</span><span class="style3"> and </span><span class="style4">fscanf()</span><span class="style3"> functions are very similar to </span><span class="style4">printf()</span><span class="style3"> and </span><span class="style4">scanf()</span><span class="style3"> except that their first argument is a </span><span class="style4">FILE</span><span class="style3"> pointer:
</span><span class="style4">
int fprintf(FILE *stream, const char *format_string, ...);
int fscanf(FILE *stream, const char *format_string, ...);</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>213</text>
</content>
<name></name>
<script></script>
</card>
card_58064.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">he </span><span class="style4">fclose()</span><span class="style3"> function should be used to close the stream and its associated file after use. For example, to write text to the file </span><span class="style18">output.fil</span><span class="style3">:
</span><span class="style4">
# include <stdio.h>
.
.
FILE *fp; // declare pointer to a FILE type
fp = fopen("output.fil","w"); // creates new file if non-existant
if (fp != NULL)
{ fprintf(fp,"Here's some output: %d\n",99);
fclose(fp);
}
</span><span class="style3">Note that </span><span class="style4">fopen()</span><span class="style3"> returns the </span><span class="style4">NULL</span><span class="style3"> pointer (defined in </span><span class="style18">stddef.h</span><span class="style3">) if it is unable to open the stream.
There are many other useful standard I/O functions available for binary I/O, non-sequential access, etc.</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>214</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p215</text>
</content>
<name></name>
<script></script>
</card>
card_34612.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">'s standard math functions are contained in the ANSI library. The standard header file </span><span class="style18">math.h</span><span class="style3"> contains declarations for these functions:
</span><span class="style4">
# include <math.h>
</span><span class="style3">C does not provide an exponentiation operator; instead the standard </span><span class="style4">pow()</span><span class="style3"> function is used. This function returns x raised to the power y. If x is negative then y must be integral. Its prototype is:
</span><span class="style4">
double pow(double x, double y);
</span><span class="style3">The </span><span class="style4">sqrt()</span><span class="style3"> function returns the (double precision) square root of its argument. Most of the common trigonometric functions are also available, returning doubles: </span><span class="style4">sin()</span><span class="style3">, </span><span class="style4">cos()</span><span class="style3">, </span><span class="style4">tan()</span><span class="style3">, </span><span class="style4">asin()</span><span class="style3">, </span><span class="style4">acos()</span><span class="style3">, </span><span class="style4">atan</span><span class="style3">, </span><span class="style4">exp()</span><span class="style3">, </span><span class="style4">log()</span><span class="style3">, </span><span class="style4">log10()</span><span class="style3">, </span><span class="style4">cosh()</span><span class="style3">, </span><span class="style4">sinh()</span><span class="style3">, </span><span class="style4">tanh()</span><span class="style3">. The </span><span class="style4">abs()</span><span class="style3"> function computes the absolute value of an integer while </span><span class="style4">fabs()</span><span class="style3"> works for doubles.</span></text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p223</text>
</content>
<name></name>
<script></script>
</card>
card_34876.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">hile the language itself provides little assistance with handling character strings, the standard string functions (contained in the ANSI library) give C programmers the capability to manipulate strings easily. These functions are declared in </span><span class="style18">string.h</span><span class="style3">:
</span><span class="style4">
# include <string.h>
</span><span class="style3">Strings in C are character arrays terminated with the null character '</span><span class="style4">\0</span><span class="style3">' (backslash- zero). Since the name of an array is a pointer to the beginning of the array, most of the standard string functions accept a character pointer as an argument. A string constant is a sequence of characters enclosed in double quotes. The null character is provided automatically and the constant is treated as an array name. Since C does not provide built-in array copying capability, the </span><span class="style4">strcpy()</span><span class="style3"> function is used:
</span><span class="style4">
char str1[80];
strcpy(str1,"Hello, world!");
</span><span class="style3">The </span><span class="style4">strcpy()</span><span class="style3"> function copies each character of the string pointed to by its second argument to the corresponding element of the string pointed to by its first argument</span></text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p223</text>
</content>
<name></name>
<script></script>
</card>
card_58255.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">mimicking the right-to-left action of the</span><span class="style4"> = </span><span class="style3">assignment operator).
It is important to distinguish among string constants, character arrays, and character pointers variables, all of which are treated as character pointers. When a character pointer variable is declared, no space is yet allocated for a character array. Therefore it is appropriate to use the</span><span class="style4"> = </span><span class="style3">assignment operator to assign to the pointer variable a pointer to a string, but it is unwise to use</span><span class="style4"> strcpy() </span><span class="style3">to assign to the unallocated portion of memory initially pointed to by the pointer variable. On the other hand when a character array is declared, space is allocated for the array elements. However, an array name is a constant pointer so it may not be assigned to. Also, in ANSI C it is illegal to assign a new value to a string constant:
</span><span class="style4">
char *ptr1, ptr2[80], *ptr3; // two character pointers and one array
ptr1 = "Hello, world!"; // ptr1 now points to the constant string
*(ptr1+7) = 'x'; // illegal! Attempts to change 'w' in constant string
ptr2 = "Hello, world!"; // illegal! ptr2 is pointer constant, not variable
strcpy(ptr3,"Hello!"); // incorrect! Copies string to unallocated memory
</span><span class="style3">
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>217</text>
</content>
<name></name>
<script></script>
</card>
card_58593.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">nother frequently-used standard string function is </span><span class="style4">strlen()</span><span class="style3">, which returns the length of the string pointed to by its argument, not including the terminating null character.
The </span><span class="style4">strcmp()</span><span class="style3"> function accepts two character pointers as its arguments and returns either 0 if the strings pointed to are equal, a positive integer if the first string is greater than the second, or a negative integer if the second string is greater than the first.
The </span><span class="style4">strstr()</span><span class="style3"> function returns a pointer to the first occurrence of the string pointed to by its second argument within the string pointed to by its first argument (disregarding the null terminator of the second string) or the </span><span class="style4">NULL</span><span class="style3"> pointer if no match is found.
There are several other standard string functions for concatenating strings, converting strings of digits to integer or double values, etc.</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>218</text>
</content>
<name></name>
<script></script>
</card>
card_35106.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">ynamic memory management is frequently used in TC and C++ to allocate and deallocate objects. </span><span class="style4">new</span><span class="style3"> and </span><span class="style4">delete</span><span class="style3"> are built-in operators which may be applied to object (or non-objects in C++ only) "free-store" variables.
The standard </span><span class="style4">malloc()</span><span class="style3"> and </span><span class="style4">free()</span><span class="style3"> functions may be used to dynamically allocate and deallocate non-objects (such as floats, character strings, or user-defined structures) in ANSI C. (In truth, a third method is commonly used in Macintosh C programs: non-portable calls to the Macintosh memory-management Toolbox routines via the MacTraps library.) These functions are defined in the ANSI library and declared in </span><span class="style18">stdlib.h</span><span class="style3">.
</span><span class="style4">
# include <stdlib.h>
</span><span class="style3">The prototype for </span><span class="style4">malloc()</span><span class="style3"> is:
</span><span class="style4">
void *malloc(size_t num_of_bytes);</span></text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p223</text>
</content>
<name></name>
<script></script>
</card>
card_58754.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">he </span><span class="style4">size_t</span><span class="style3"> type is defined in </span><span class="style18">stdlib.h</span><span class="style3"> and is typically an unsigned long integer. The </span><span class="style4">malloc()</span><span class="style3"> function returns a pointer to a block of memory of the desired size. This is a </span><span class="style4">void</span><span class="style3"> pointer, meaning that it may be assigned to a pointer of any type.
The number of bytes required is frequently determined using the </span><span class="style4">sizeof</span><span class="style3"> operator, which evaluates the number of bytes required by its operand. An example using the </span><span class="style4">personnel_rec</span><span class="style3"> user-defined type discussed earlier* is:
</span><span class="style3">The </span><span class="style4">free()</span><span class="style3"> function deallocates the space pointed to by its argument.</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>220</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>25150</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>personnel_rec structure</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>personnel_rec structure - p75</text>
</content>
<name></name>
<script></script>
</card>
card_59075.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">ote that a cast operator* is used to convert the </span><span class="style4">void</span><span class="style3"> pointer returned by </span><span class="style4">malloc()</span><span class="style3"> to the desired type. This is not strictly necessary since automatic type conversion will take place upon assignment.
Dynamic memory allocation is often used when the amount of memory needed by an application is not known before run-time. The program may define a large array of pointers to data structures, but dynamically allocate the individual data structures pointed to by elements of the array only as needed:
</span><span class="style4">
struct personnel_rec *p_arr[1000]; // doesn't yet allocate any
// personnel_rec's
.
.
p_arr[i] = malloc(sizeof (struct personnel_rec)); // allocate ith element
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>221</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>47191</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>Casts for type conversion</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>Casts for type conversion - p175</text>
</content>
<name></name>
<script></script>
</card>
card_23089.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text>A program's efficiency may be a measure of its raw processing speed. However as both hardware performance and user expectations continue to rise rapidly, this sort of efficiency is subordinate to the efficiency of the overall software lifecycle.
Programmers naturally strive for efficiency by attempting to minimize the amount of future effort a program will generate. This often involves tradeoffs among short-term and long-term investments by the programmer, and ease of use and flexibility from the user's perspective.
This chapter discusses programming issues related to code reusability, portability, and user-interface design in the context of TC and C++. Code for potentially-portable 2-dimensional graphics and for a simple menu-driven application framework is included.
</text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>222</text>
</content>
<content>
<layer>background</layer>
<id>17</id>
<text>p250</text>
</content>
<name></name>
<script></script>
</card>
card_60165.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">he object-oriented programming (OOP) approach facilitated by Think C and C++ provides the potential for vast improvements in the </span><span class="style7">maintenance and reuse of source code</span><span class="style3">. Code maintainability generally depends on how easily the source code can be adapted to changing user requirements. This sort of code reuse differs only in degree from the use of portions of existing source code in entirely new programming efforts.
By encapsulating data with the procedures which act upon the data the programmer can construct modular applications, which encourage the reuse of data </span><span class="style7">objects</span><span class="style3"> (Chapter 4). OOP languages like TC/C++ provide syntactical assistance for such encapsulation. More importantly, they allow the definition of </span><span class="style7">classes</span><span class="style3"> of objects and the construction of </span><span class="style7">derived</span><span class="style3"> classes. Since even the most modular code often requires customization for reuse in a new programming situation, the ability to easily construct new classes which </span><span class="style7">inherit</span><span class="style3"> the data structures and functionality of an existing class has great significance.
Applications should be constructed as a collection of interacting objects, each of </span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>223</text>
</content>
<name></name>
<script></script>
</card>
card_61545.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">hich represents a data structure and its interface. When an existing class must be altered significantly to obtain the desired functionality, the programmer should instead derive a new class.
On the other hand, the programmer should inspect the structure of any new class to determine whether a more general </span><span class="style7">abstract</span><span class="style3"> class (of which an object is never defined) can instead be defined. The desired class may then be derived from the more general class, which itself has a greater likelyhood of reuse in future programming efforts. This approach also helps simplify future maintentance of the application.
Abstract classes in turn may derive from still more general classes, to create a tree-shaped class hierarchy. (The multiple inheritance property of C++ v.2.0 and later allows non-tree-shaped structures.) Often all classes used in an application are derived from a single </span><span class="style7">root</span><span class="style3"> class, such as the Generic_Class used in the example in Chapter 4. This simplifies changing certain basic characteristics which are common to all classes.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>224</text>
</content>
<name></name>
<script></script>
</card>
card_61949.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3"> collection of related general-purpose classes may be organized to form a </span><span class="style7">class library</span><span class="style3">* for use in future programming efforts. This sort of library may be distri- buted in precompiled modules rather than in the form of source code. Interestingly, programmers may derive new classes from those supplied in such libraries without need for access to the proprietary source code.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>225</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>62767</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>Class libraries</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>Class libraries - p234</text>
</content>
<name></name>
<script></script>
</card>
card_61284.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">estriction to writing completely portable programs prevents the programmer from taking advantage of useful features specific to a single environment. For example the Macintosh ROM "Toolbox" provides many invaluable routines for writing Macintosh programs.
It is often possible to confine non-portable code to individual program modules to allow reuse of the remaining code in other environments. The example at the end of this section shows how to isolate non-portable graphics code by defining an abstract class from which machine-specific versions may be derived. The particular object instantiated is selected to match the hardware needs.
A significant obstacle to portability results when targeting platforms using traditional command or menu-driven user interfaces and platforms using a Macintosh-style event-driven user interface. The flow of control within software developed for the former type of interface is radically different from that in software developed for the latter. It is anticipated that the study of </span><span class="style7">user interface management systems</span><span class="style3"> (UIMS) may lead to improved code reuse in such circumstances.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>226</text>
</content>
<name></name>
<script></script>
</card>
card_6548.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text>A UIMS establishes an additional programming layer consisting of an abstract definition of the application's user interface. The implementation of this abstract definition may be done in a variety of ways. For example, a request for a selection by the user may be implemented via a command-line prompt or by polling a pointing device such as a mouse. If all references to the user interface are made via the new programming layer, it becomes possible to vary the implementation of the user interface without altering the functional portion of the program. That is, the application-specific portion of the program may be combined with any one of several existing user interface modules to produce a complete application with the desired user interface. Changing the user interface requires only swapping user interface modules and recompiling.
Although general-purpose UIMS implementations have seen little commercial application to date, the underlying technique of abstracting the user interface is often incorporated into commercial applications to encourage portability. The potential exists to extend portability beyond the consideration of alternative harware platforms, to encompass portability among alternative user interfaces as well.
</text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>227</text>
</content>
<name></name>
<script></script>
</card>
card_66237.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
The files listed in the following pages implement the abstract Generic_SScreen ("simple screen") class for general-purpose 2-dimensional graphics combined with stdio-style output. The Mac_SScreen class is derived from this class for use on the Macintosh, but versions for DOS or UNIX-based graphics environments may readily be derived as well. Applications which use SScreen objects for graphics will then be portable to other environments.
The files </span><span class="style18">class.h</span><span class="style3"> and </span><span class="style18">class.c</span><span class="style3"> given in Chapter 4 are also required. Think C's MacTraps library is required for applications using the Mac_SScreen class, in order to gain access to the Macintosh graphics routines. Think C's "Prefix" option should contain "# include <MacHeaders>" in order to properly declare these graphics routines.
An example application is also included.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>228</text>
</content>
<name></name>
<script></script>
</card>
card_66370.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3"> </span><span class="style7">class library</span><span class="style3"> is a collection of classes defined with an object oriented language like Think C or C++. It usually provides general functionality in a specific area, such as mathematics, graphics, or memory management. A programmer may call upon the services of an existing class library to reduce the overall effort required to create a new application. This is analogous to the use of procedure libraries in traditional programming languages.
The OOP approach encourages the programmer to modify the functionality of an existing class library by deriving custom classes. The programmer may make this customization without having to learn the details of the original implementation. This increases the likelyhood of success for this form of code reuse.
As mentioned earlier, proprietary source code may be protected while allowing its functionality to be customized, by distributing the class library in the form of object code. The purchaser may derive new classes from the existing ones without benefit of the source code. </span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>234</text>
</content>
<content>
<layer>background</layer>
<id>6</id>
<text>9.3 Class Libraries</text>
</content>
<name></name>
<script></script>
</card>
card_64723.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
An </span><span class="style7">application framework</span><span class="style3"> is a body of code which encapsulates the general structures governing the flow of control in applications. One form of application framework is a class library which provides a generic </span><span class="style4">Application</span><span class="style3"> class, from which the programmer may derive a specific application.
Application frameworks are especially useful to reduce the effort required to design an event-driven application. Typically, a generic </span><span class="style4">Application</span><span class="style3"> class for such an environment will include the event loop which looks for events (key presses, mouse clicks, etc.) and invokes the appropriate responses. Derived applications simply register information about their user interface and the application-specific responses for user events, inheriting the event processing engine from the generic class.
The next section briefly describes the event-driven Think Class Library, followed by code for a much simpler example of an application framework.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>235</text>
</content>
<name></name>
<script></script>
</card>
card_73623.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
In addition to the standard C function libraries and specialized function libraries for the Macintosh (which call the Macintosh Toolbox ROM routines), Think C comes with the Think Class Library (TCL). The TCL contains an application framework defining many useful classes for writing Macintosh applications.
TCL classes encapsulate the data and functionality needed to implement an event-driven </span><span class="style4">Application</span><span class="style3"> dealing with </span><span class="style4">Files</span><span class="style3">, </span><span class="style4">Windows</span><span class="style3">, </span><span class="style4">ScrollBars</span><span class="style3">, </span><span class="style4">Pictures</span><span class="style3">, </span><span class="style4">EditText</span><span class="style3"> fields, </span><span class="style4">CheckBoxes</span><span class="style3">, etc.
In this way many of the complexities of the Macintosh graphical user interface are "hidden" from the programmer, yet the programmer has the ability to derive new classes from the TCL classes to obtain specialized functionality.
The Think C manuals discuss the functioning of the TCL in detail. A working knowledge of the Macintosh Toolbox ROM routines is recommended for using the
</span></text>
</content>
<name></name>
<script></script>
</card>
card_73880.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text>TCL to construct applications faithful to the Macintosh interface.
Similar graphics class libraries exist in several C++ environments. The potential exists for the standardization of class libraries such as the TCL, to allow cross-platform development using graphical user interfaces.*
</text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>237</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>61284</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>Portability</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>Portability - p226</text>
</content>
<name></name>
<script></script>
</card>
card_65394.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">N APPLICATION FRAMEWORK EXAMPLE
The following pages contain source code for a simple Think C/C++ application framework. Each page contains a scrolling text field whose contents may be pasted into an individual file for compilation. The files </span><span class="style18">class.h</span><span class="style3"> and </span><span class="style18">class.c</span><span class="style3"> from the example in Chapter 4 are also required.
The </span><span class="style4">Generic_App</span><span class="style3"> class handles menu-driven applications, with the restriction of a text-only (stdio) interface. The programmer must define a new class whose parent is </span><span class="style4">Generic_App</span><span class="style3">. In this example, the new class is </span><span class="style4">Data_App</span><span class="style3">, and represents a simplified database-type application. Instructions on deriving your own applications are given in </span><span class="style18">app.h</span><span class="style3">.
</span><span class="style4">Data_App</span><span class="style3"> is initialized by associating command names with pointers to the methods to be invoked in response to each command. The </span><span class="style4">run()</span><span class="style3"> method inherited from </span><span class="style4">Generic_App</span><span class="style3"> produces the specified user interface and handles menu selections automatically.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>238</text>
</content>
<name></name>
<script></script>
</card>
card_65642.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">hink C is an integrated editor-compiler-linker-debugger environment. During development the user's program is maintained in a </span><span class="style7">project</span><span class="style3"> file, whose name is normally given the π (pi) symbol extension, Option-P in Geneva font. This file keeps track of all the source files, header files, and libraries which make up the program, and also stores the object code for all the files which have compiled successfully. The project file, headers, and sources are usually kept together in a folder.
Similar to the UNIX "make" utility, Think C decides which source files will require recompilation due to changes to source or header files.
When beginning a new project, the user must add to the project his/her source files, by choosing "Add..." from the "Source" menu. Header files are not added since after preprocessing these become part of the referencing source file(s).
The user must also "Add..." all the required function libraries, which are provided in precompiled form. For example, the ANSI library contains all the ANSI standard functions for I/O, string handling, math, and memory management. The MacTraps</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>248</text>
</content>
<content>
<layer>background</layer>
<id>6</id>
<text>Appendix 1. The Think C Project </text>
</content>
<name></name>
<script></script>
</card>
card_59872.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text>library allows access to the Macintosh Toolbox routines, most of which are contained in the Macintosh ROMs. The oops library contains TC's object-oriented programming extensions, discussed in Chapter 4. The unix library provide functions useful for UNIX compatibility. Most TC applications require at least the ANSI and oops libraries.
Since the ANSI library is nearly the size of a single segment (32 kbyte), it is often necessary to "drag" the ANSI library in the Project window down into a new segment.
To use the object-oriented extensions to ANSI C, select the "Think C + Objects" language option. It is also recommended that the "Require prototypes" language option be selected, since this helps avoid programming errors.
Once the required source files and libraries have been added and the options set, the user may compile the source files and load the libraries simply by choosing "Bring Up To Date" from the Project menu. If no compilation errors are reported the user </text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>249</text>
</content>
<name></name>
<script></script>
</card>
card_7135.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text>chooses "Run". If no linking errors are reported (for example if the required library had not been added) the program will execute. Choosing "Build Application..." creates a stand-alone application, if desired.
Refer to the Think C User's Manual for details on file/folder organization, writing, segmenting, and compiling programs, building applications, and using the debugger.
</text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>250</text>
</content>
<name></name>
<script></script>
</card>
card_12288.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text>Think C v. 5.0 offers complete ANSI C compatibility, a few crucial C++ features which allow object-oriented programming, and a few features not available in C++. C++ on the other hand is mostly ANSI C compatible and adds several features not available in TC.
This appendix details the differences among ANSI C, Think C v. 5.0, and C++, including requirements for portability from TC to C++. (Since C++ has many more features, it is generally difficult to port in the other direction.)
</text>
</content>
<name></name>
<script></script>
</card>
card_4500.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
The ANSI standard of C adds several features to traditional versions of C and helps to unify its development. The most notable changes are: function prototyping, </span><span class="style4">void</span><span class="style3"> types, the </span><span class="style4">const</span><span class="style3"> and </span><span class="style4">volatile</span><span class="style3"> qualifiers, and miscellaneous library changes.
The Language Reference in the Think C User's Manual describes the behavior which the standard allows as "implementation defined". Most significant to object-oriented programming is the "</span><span class="style4">#pragma once</span><span class="style3">" directive, to avoid multiple inclusion of header files.* This directive should be avoided where portability is a concern.
The "Language Settings" options may be used to affect Think C's level of ANSI conformance.
</span></text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>54516</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>Multiple header inclusion</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>Multiple header inclusion - p201</text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>252</text>
</content>
<name></name>
<script></script>
</card>
card_59314.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
Think C 5.0 extends ANSI C with several C++ features, as detailed in Chapter 4. Most importantly, the definition of a user-defined type may contain function prototypes, in which case the structure is called a </span><span class="style7">class</span><span class="style3">. These member functions (or </span><span class="style7">methods</span><span class="style3">) may refer directly to variables which are members of the same class; that is, these </span><span class="style7">instance variables</span><span class="style3"> are said to have "class scope".
When a pointer to a variable of class type is declared, the variable is called an </span><span class="style7">object</span><span class="style3">. Space for this variable is allocated dynamically using the </span><span class="style7">free-store</span><span class="style3"> operator </span><span class="style4">new</span><span class="style3">. (The </span><span class="style4">new()</span><span class="style3"> function was used instead in the previous version Think C 4.x.) The variable is deallocated using the </span><span class="style4">delete</span><span class="style3"> operator.
Significantly, object references are usually implemented as Macintosh "handles" in TC, which requires care when taking the address of instance variables.* This is not generally the case with C++.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>253</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>38494</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>TC direct and indirect objects</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>TC direct and indirect objects - p158</text>
</content>
<name></name>
<script></script>
</card>
card_60082.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">ew classes can be defined which are derived from existing classes. The derived classes </span><span class="style7">inherit</span><span class="style3"> all the instance variables and methods of the base class, and may add additional variables and methods or redefine ("override") an existing method. TC provides the </span><span class="style4">inherited</span><span class="style3"> keyword — not available in C++ — to simplify access to the original method from within an overriding definition.
The scope resolution operator :: is used when defining methods and when calling methods without refering to a particular object. The </span><span class="style4">this</span><span class="style3"> identifier is used to refer to the object receiving a message.
With Think C version 5.0, class definitions may include the </span><span class="style4">class</span><span class="style3"> and </span><span class="style4">virtual</span><span class="style3"> keywords. </span><span class="style7">When the "Methods are virtual by default" option is turned off, the root class is declared with the </span><span class="style22">class</span><span class="style7"> keyword (so that the storage specifier* may be omitted), and the </span><span class="style22">inherited</span><span class="style7"> and "</span><span class="style22">#pragma once</span><span class="style7">" features are not used, it is possible for Think C programs to compile equally under C++.</span><span class="style3">
Version 5.0 also incorporates the C++ features of class </span><span class="style7">access control</span><span class="style3">, </span><span class="style7">constructors</span><span class="style3"> </span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>254</text>
</content>
<content>
<layer>background</layer>
<id>29</id>
<text>43452</text>
</content>
<content>
<layer>background</layer>
<id>27</id>
<text>Class storage specifier</text>
</content>
<content>
<layer>background</layer>
<id>20</id>
<text>Class storage specifier - p142</text>
</content>
<name></name>
<script></script>
</card>
card_66814.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style7">nd destructors</span><span class="style3">, </span><span class="style7">allocators and deallocators</span><span class="style3">, and </span><span class="style7">static members</span><span class="style3">. Access control enhances modularity be restricting access to certain instance variables and methods of a class. Constructors and destructors are methods which are automatically invoked when allocating and deallocating objects. Allocators and deallocators allow the programmer to customize the creation and deletion of objects. Instance variables and methods declared </span><span class="style4">static</span><span class="style3"> are shared by all objects of a given class.
TC extends ANSI C with a few non-object-oriented features. TC supplies specialized libraries for Macintosh programming. The storage class </span><span class="style4">pascal</span><span class="style3"> and support for Pascal string definitions simplifies access to the Macintosh Toolbox ROM routines. C++ style comments (</span><span class="style4">//</span><span class="style3">) are now supported.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>255</text>
</content>
<name></name>
<script></script>
</card>
card_59590.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
C++ provides most of the object extensions available in TC plus additional object-oriented features.
Significantly, it is possible to declare identifiers which are themselves objects, rather than pointers to objects as required in TC. Constructors may take arguments. These features — together with the ability to define variables at their first point of use (see below) — simplify the problem of object allocation.
Access control is further customized with the </span><span class="style4">friend</span><span class="style3"> specifier. With version 2.0, C++ offers </span><span class="style7">multiple inheritance</span><span class="style3">, where a derived class may inherit members from more than one base class. Arguably, these capabilities complicate inter-class relationships.
C++ also offers several additions to ANSI C and Think C which are not directly related to object-oriented programming, as discussed below.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>256</text>
</content>
<name></name>
<script></script>
</card>
card_60577.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">n C++ declarations may occur anywhere within a function, rather than preceding all executable statements. This encourages the declaration and initialization of automatic variables immediately prior to their point of use. In addition, the "free-store" </span><span class="style4">new</span><span class="style3"> and </span><span class="style4">delete</span><span class="style3"> operators may be applied to all data types.
C++ provides function and operator </span><span class="style7">overloading</span><span class="style3">; that is, a function or operator may be defined to operate in a way which depends upon the context in which it is used. This complements the polymorphism property of the object-oriented approach.
C++ provides the alternative I/O header file </span><span class="style18">stream.h</span><span class="style3"> which defines the overloaded operators </span><span class="style4">>></span><span class="style3"> and </span><span class="style4"><<</span><span class="style3"> for input and output. These offer greater convenience and efficiency than </span><span class="style4">scanf()</span><span class="style3"> and </span><span class="style4">printf()</span><span class="style3"> since the processing appropriate to the given operands is selected automatically.
C++ functions may employ "call by reference" more conveniently than the usual technique of passing a pointer, by using </span><span class="style7">reference variables</span><span class="style3">.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>257</text>
</content>
<name></name>
<script></script>
</card>
card_60773.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">++ </span><span class="style7">inline expanded functions</span><span class="style3"> offer the efficiency of macro substitution without its associated syntactical difficulties.
C++ version 3.0 continues to add features, most notably </span><span class="style7">templates</span><span class="style3"> (generic types) for improved efficiency in code reuse.
</span></text>
</content>
<content>
<layer>background</layer>
<id>7</id>
<text>258</text>
</content>
<name></name>
<script></script>
</card>
card_2231.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
This stack is based on Bookbinder, a $10 shareware stack by Ralph Gonzalez, PO Box 54, Newark, DE 19711. Press the buttons to view new pages. The left and right arrow buttons will move you one page at a time. An asterix (*) in the text indicates a relevant button or footnote at the bottom of the page. After pressing this button, the bent arrow returns you to the page you were reading. Press the book icon to insert a bookmark at a page, so you can return to that page at a later date.
You may obtain a hard copy of the stack by using HyperCard's Print Stack feature in the File menu.</text>
</content>
<content>
<layer>card</layer>
<id>2</id>
<text>Bookbinder</text>
</content>
<name>help</name>
<script>on openCard
if card field "return card" is "" then
hide card button "return"
else
show card button "return"
end if
end openCard
on closeCard
global gettingHelp
if gettingHelp is false then
put "" into card field "return card" of card "help"